/[pkg-coolkey]/coolkey/trunk/debian/patches/coolkey-cac.patch
ViewVC logotype

Contents of /coolkey/trunk/debian/patches/coolkey-cac.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 39 - (show annotations) (download)
Fri Dec 24 05:27:49 2010 UTC (2 years, 5 months ago) by bottoms
File size: 29641 byte(s)
upstream coolkey-cac.patch
1 --- a/src/coolkey/slot.cpp
2 +++ b/src/coolkey/slot.cpp
3 @@ -372,7 +372,7 @@
4 : log(log_), readerName(NULL), personName(NULL), manufacturer(NULL),
5 slotInfoFound(false), context(context_), conn(NULL), state(UNKNOWN),
6 isVersion1Key(false), needLogin(false), fullTokenName(false),
7 - mCoolkey(false),
8 + mCoolkey(false), mOldCAC(false),
9 #ifdef USE_SHMEM
10 shmem(readerName_),
11 #endif
12 @@ -412,6 +412,9 @@
13 }
14 CKYBuffer_InitEmpty(&cardATR);
15 CKYBuffer_InitEmpty(&mCUID);
16 + for (int i=0; i < MAX_CERT_SLOTS; i++) {
17 + CKYBuffer_InitEmpty(&cardAID[i]);
18 + }
19 } catch(PKCS11Exception &) {
20 if (conn) {
21 CKYCardConnection_Destroy(conn);
22 @@ -479,6 +482,9 @@
23 CKYBuffer_FreeData(&nonce);
24 CKYBuffer_FreeData(&cardATR);
25 CKYBuffer_FreeData(&mCUID);
26 + for (int i=0; i < MAX_CERT_SLOTS; i++) {
27 + CKYBuffer_FreeData(&cardAID[i]);
28 + }
29 }
30
31 template <class C>
32 @@ -671,15 +677,9 @@
33 status = CKYApplet_SelectCoolKeyManager(conn, NULL);
34 if (status != CKYSUCCESS) {
35 log->log("CoolKey Select failed 0x%x\n", status);
36 - status = CACApplet_SelectPKI(conn, 0, NULL);
37 + status = getCACAid();
38 if (status != CKYSUCCESS) {
39 - log->log("CAC Select failed 0x%x\n", status);
40 - if (status == CKYSCARDERR) {
41 - log->log("CAC Card Failure 0x%x\n",
42 - CKYCardConnection_GetLastError(conn));
43 - disconnect();
44 - }
45 - return;
46 + goto loser;
47 }
48 state |= CAC_CARD | APPLET_SELECTABLE | APPLET_PERSONALIZED;
49 /* skip the read of the cuid. We really don't need it and,
50 @@ -690,6 +690,15 @@
51 needLogin = 1;
52 mCoolkey = 0;
53 return;
54 +
55 +loser:
56 + log->log("CAC Select failed 0x%x\n", status);
57 + if (status == CKYSCARDERR) {
58 + log->log("CAC Card Failure 0x%x\n",
59 + CKYCardConnection_GetLastError(conn));
60 + disconnect();
61 + }
62 + return;
63 }
64 mCoolkey = 1;
65 log->log("time connect: Select Applet %d ms\n", OSTimeNow() - time);
66 @@ -771,17 +780,111 @@
67 invalidateLogin(false);
68 }
69
70 +CKYStatus
71 +Slot::getCACAid()
72 +{
73 + CKYBuffer tBuf;
74 + CKYBuffer vBuf;
75 + CKYSize tlen, vlen;
76 + CKYOffset toffset, voffset;
77 + int certSlot = 0;
78 + int i,length = 0;
79 + CKYStatus status;
80 +
81 + CKYBuffer_InitEmpty(&tBuf);
82 + CKYBuffer_InitEmpty(&vBuf);
83 +
84 + /* clear out the card AID's */
85 + for (i=0; i < MAX_CERT_SLOTS; i++) {
86 + CKYBuffer_Resize(&cardAID[i],0);
87 + }
88 +
89 + status = CACApplet_SelectCCC(conn,NULL);
90 + if (status != CKYSUCCESS) {
91 + /* are we an old CAC */
92 + status = CACApplet_SelectPKI(conn, &cardAID[0], 0, NULL);
93 + if (status != CKYSUCCESS) {
94 + /* no, just fail */
95 + return status;
96 + }
97 + /* yes, fill in the old applets */
98 + mOldCAC = true;
99 + for (i=1; i< MAX_CERT_SLOTS; i++) {
100 + CACApplet_SelectPKI(conn, &cardAID[i], i, NULL);
101 + }
102 + return CKYSUCCESS;
103 + }
104 + /* definately not an old CAC */
105 + mOldCAC = false;
106 +
107 + /* read the TLV */
108 + status = CACApplet_ReadFile(conn, CAC_TAG_FILE, &tBuf, NULL);
109 + if (status != CKYSUCCESS) {
110 + goto done;
111 + }
112 + status = CACApplet_ReadFile(conn, CAC_VALUE_FILE, &vBuf, NULL);
113 + if (status != CKYSUCCESS) {
114 + goto done;
115 + }
116 + tlen = CKYBuffer_Size(&tBuf);
117 + vlen = CKYBuffer_Size(&vBuf);
118 +
119 + for(toffset = 2, voffset=2;
120 + certSlot < MAX_CERT_SLOTS && toffset < tlen && voffset < vlen ;
121 + voffset += length) {
122 +
123 + CKYByte tag = CKYBuffer_GetChar(&tBuf, toffset);
124 + length = CKYBuffer_GetChar(&tBuf, toffset+1);
125 + toffset += 2;
126 + if (length == 0xff) {
127 + length = CKYBuffer_GetShortLE(&tBuf, toffset);
128 + toffset +=2;
129 + }
130 + if (tag != CAC_TAG_CARDURL) {
131 + continue;
132 + }
133 + /* CARDURL tags must be at least 10 bytes long */
134 + if (length < 10) {
135 + continue;
136 + }
137 + /* check the app type, should be TLV_APP_PKI */
138 + if (CKYBuffer_GetChar(&vBuf, voffset+5) != CAC_TLV_APP_PKI) {
139 + continue;
140 + }
141 + status = CKYBuffer_AppendBuffer(&cardAID[certSlot], &vBuf, voffset, 5);
142 + if (status != CKYSUCCESS) {
143 + goto done;
144 + }
145 + status = CKYBuffer_AppendBuffer(&cardAID[certSlot], &vBuf,
146 + voffset+8, 2);
147 + if (status != CKYSUCCESS) {
148 + goto done;
149 + }
150 + cardEF[certSlot] = CKYBuffer_GetShortLE(&vBuf, voffset+6);
151 +
152 + certSlot++;
153 + }
154 + status = CKYSUCCESS;
155 + if (certSlot == 0) {
156 + status = CKYAPDUFAIL; /* probably neeed a beter error code */
157 + }
158 +
159 +done:
160 + CKYBuffer_FreeData(&tBuf);
161 + CKYBuffer_FreeData(&vBuf);
162 + return status;
163 +}
164 +
165 void
166 Slot::refreshTokenState()
167 {
168 if( cardStateMayHaveChanged() ) {
169 -log->log("card changed\n");
170 + log->log("card changed\n");
171 invalidateLogin(true);
172 closeAllSessions();
173 unloadObjects();
174 connectToToken();
175
176 -
177 if( state & APPLET_PERSONALIZED ) {
178 try {
179 loadObjects();
180 @@ -1019,7 +1122,7 @@
181
182 struct _manList {
183 unsigned short type;
184 - char *string;
185 + const char *string;
186 };
187
188 static const struct _manList manList[] = {
189 @@ -1280,13 +1383,30 @@
190 Slot::selectCACApplet(CKYByte instance)
191 {
192 CKYStatus status;
193 - status = CACApplet_SelectPKI(conn, instance, NULL);
194 + CKYBuffer *aid = &cardAID[instance];
195 +
196 + if (CKYBuffer_Size(aid) == 0) {
197 + disconnect();
198 + throw PKCS11Exception(CKR_DEVICE_REMOVED);
199 + return;
200 + }
201 +
202 + status = CKYApplet_SelectFile(conn, aid, NULL);
203 if ( status == CKYSCARDERR ) handleConnectionError();
204 if ( status != CKYSUCCESS) {
205 // could not select applet: this just means it's not there
206 disconnect();
207 throw PKCS11Exception(CKR_DEVICE_REMOVED);
208 }
209 + if (mOldCAC) {
210 + return;
211 + }
212 + status = CACApplet_SelectFile(conn, cardEF[instance], NULL);
213 + if ( status == CKYSCARDERR ) handleConnectionError();
214 + if ( status != CKYSUCCESS) {
215 + disconnect();
216 + throw PKCS11Exception(CKR_DEVICE_REMOVED);
217 + }
218 }
219 // assume we are already in a transaction
220 void
221 @@ -2059,10 +2179,85 @@
222 return objInfoList;
223 }
224
225 +CKYStatus
226 +Slot::readCACCertificateFirst(CKYBuffer *cert, CKYSize *nextSize,
227 + bool throwException)
228 +{
229 + CKYStatus status;
230 + CKYISOStatus apduRC;
231 +
232 + if (mOldCAC) {
233 + /* get the first 100 bytes of the cert */
234 + status = CACApplet_GetCertificateFirst(conn, cert, nextSize, &apduRC);
235 + if (throwException && (status != CKYSUCCESS)) {
236 + handleConnectionError();
237 + }
238 + return status;
239 + }
240 +
241 + CKYBuffer tBuf;
242 + CKYBuffer vBuf;
243 + CKYSize tlen, vlen;
244 + CKYOffset toffset, voffset;
245 + int length = 0;
246 +
247 + CKYBuffer_InitEmpty(&tBuf);
248 + CKYBuffer_InitEmpty(&vBuf);
249 + CKYBuffer_Resize(cert, 0);
250 +
251 + /* handle the new CAC card read */
252 + /* read the TLV */
253 + status = CACApplet_ReadFile(conn, CAC_TAG_FILE, &tBuf, NULL);
254 + if (status != CKYSUCCESS) {
255 + goto done;
256 + }
257 + status = CACApplet_ReadFile(conn, CAC_VALUE_FILE, &vBuf, NULL);
258 + if (status != CKYSUCCESS) {
259 + goto done;
260 + }
261 + tlen = CKYBuffer_Size(&tBuf);
262 + vlen = CKYBuffer_Size(&vBuf);
263 +
264 + /* look for the Cert out of the TLV */
265 + for(toffset = 2, voffset=2; toffset < tlen && voffset < vlen ;
266 + voffset += length) {
267 +
268 + CKYByte tag = CKYBuffer_GetChar(&tBuf, toffset);
269 + length = CKYBuffer_GetChar(&tBuf, toffset+1);
270 + toffset += 2;
271 + if (length == 0xff) {
272 + length = CKYBuffer_GetShortLE(&tBuf, toffset);
273 + toffset +=2;
274 + }
275 + if (tag != CAC_TAG_CERTIFICATE) {
276 + continue;
277 + }
278 + CKYBuffer_AppendBuffer(cert, &vBuf, voffset, length);
279 + break;
280 + }
281 + status = CKYSUCCESS;
282 +
283 +done:
284 + CKYBuffer_FreeData(&tBuf);
285 + CKYBuffer_FreeData(&vBuf);
286 + return status;
287 +}
288 +
289 +/*
290 + * only necessary for old CAC cards. New CAC cards have to read the
291 + * whole cert in anyway above....
292 + */
293 +CKYStatus
294 +Slot::readCACCertificateAppend(CKYBuffer *cert, CKYSize nextSize)
295 +{
296 + CKYISOStatus apduRC;
297 + assert(mOldCAC);
298 + return CACApplet_GetCertificateAppend(conn, cert, nextSize, &apduRC);
299 +}
300 +
301 void
302 Slot::loadCACCert(CKYByte instance)
303 {
304 - CKYISOStatus apduRC;
305 CKYStatus status = CKYSUCCESS;
306 CKYBuffer cert;
307 CKYBuffer rawCert;
308 @@ -2097,12 +2292,7 @@
309 instance, OSTimeNow() - time);
310
311 if (instance == 0) {
312 - /* get the first 100 bytes of the cert */
313 - status = CACApplet_GetCertificateFirst(conn, &rawCert,
314 - &nextSize, &apduRC);
315 - if (status != CKYSUCCESS) {
316 - handleConnectionError();
317 - }
318 + readCACCertificateFirst(&rawCert, &nextSize, true);
319 log->log("CAC Cert %d: fetch CAC Cert: %d ms\n",
320 instance, OSTimeNow() - time);
321 }
322 @@ -2143,8 +2333,7 @@
323 shmem.setVersion(SHMEM_VERSION);
324 shmem.setDataVersion(dataVersion);
325 } else {
326 - status = CACApplet_GetCertificateFirst(conn, &rawCert,
327 - &nextSize, &apduRC);
328 + status = readCACCertificateFirst(&rawCert, &nextSize, false);
329
330 if (status != CKYSUCCESS) {
331 /* CAC only requires the Certificate in pki '0' */
332 @@ -2159,8 +2348,7 @@
333 }
334
335 if (nextSize) {
336 - status = CACApplet_GetCertificateAppend(conn, &rawCert,
337 - nextSize, &apduRC);
338 + status = readCACCertificateAppend(&rawCert, nextSize);
339 }
340 log->log("CAC Cert %d: Fetch rest : %d ms\n",
341 instance, OSTimeNow() - time);
342 @@ -2176,9 +2364,10 @@
343
344 log->log("CAC Cert %d: Cert has been read: %d ms\n",
345 instance, OSTimeNow() - time);
346 - if (CKYBuffer_GetChar(&rawCert,0) == 1) {
347 + if (!mOldCAC || CKYBuffer_GetChar(&rawCert,0) == 1) {
348 CKYSize guessFinalSize = CKYBuffer_Size(&rawCert);
349 CKYSize certSize = 0;
350 + CKYOffset offset = mOldCAC ? 1 : 0;
351 int zret = Z_MEM_ERROR;
352
353 do {
354 @@ -2189,7 +2378,8 @@
355 }
356 certSize = guessFinalSize;
357 zret = uncompress((Bytef *)CKYBuffer_Data(&cert),&certSize,
358 - CKYBuffer_Data(&rawCert)+1, CKYBuffer_Size(&rawCert)-1);
359 + CKYBuffer_Data(&rawCert)+offset,
360 + CKYBuffer_Size(&rawCert)-offset);
361 } while (zret == Z_BUF_ERROR);
362
363 if (zret != Z_OK) {
364 @@ -2526,7 +2716,7 @@
365 switch( result ) {
366 case CKYISO_SUCCESS:
367 break;
368 - case 6981:
369 + case 0x6981:
370 throw PKCS11Exception(CKR_PIN_LOCKED);
371 default:
372 if ((result & 0xff00) == 0x6300) {
373 --- a/src/coolkey/slot.h
374 +++ b/src/coolkey/slot.h
375 @@ -294,6 +294,7 @@
376 const CKYBuffer *paddedOutput) const = 0;
377 };
378
379 +#define MAX_CERT_SLOTS 3
380 class Slot {
381
382 public:
383 @@ -328,6 +329,8 @@
384 CKYBuffer nonce;
385 CKYBuffer cardATR;
386 CKYBuffer mCUID;
387 + CKYBuffer cardAID[MAX_CERT_SLOTS];
388 + unsigned short cardEF[MAX_CERT_SLOTS];
389 bool isVersion1Key;
390 bool needLogin;
391 long publicFree;
392 @@ -335,6 +338,7 @@
393 long privateFree;
394 bool fullTokenName;
395 bool mCoolkey;
396 + bool mOldCAC;
397
398 //enum { RW_SESSION_HANDLE = 1, RO_SESSION_HANDLE = 2 };
399
400 @@ -398,6 +402,11 @@
401 list<ListObjectInfo> fetchCombinedObjects(const CKYBuffer *header);
402 list<ListObjectInfo> fetchSeparateObjects();
403
404 + CKYStatus getCACAid();
405 + CKYStatus readCACCertificateFirst(CKYBuffer *cert, CKYSize *nextSize,
406 + bool throwException);
407 + CKYStatus readCACCertificateAppend(CKYBuffer *cert, CKYSize nextSize);
408 +
409 void selectApplet();
410 void selectCACApplet(CKYByte instance);
411 void unloadObjects();
412 --- a/src/libckyapplet/cky_applet.c
413 +++ b/src/libckyapplet/cky_applet.c
414 @@ -41,7 +41,13 @@
415 CKYStatus
416 CKYAppletFactory_SelectFile(CKYAPDU *apdu, const void *param)
417 {
418 - return CKYAPDUFactory_SelectFile(apdu,(const CKYBuffer *)param);
419 + return CKYAPDUFactory_SelectFile(apdu, 4, 0, (const CKYBuffer *)param);
420 +}
421 +
422 +CKYStatus
423 +CACAppletFactory_SelectFile(CKYAPDU *apdu, const void *param)
424 +{
425 + return CKYAPDUFactory_SelectFile(apdu, 2, 12, (const CKYBuffer *)param);
426 }
427
428 CKYStatus
429 @@ -225,10 +231,17 @@
430 }
431
432 CKYStatus
433 -CACAppletFactory_SignDecrypt(CKYAPDU *apdu, const void *param)
434 +CACAppletFactory_SignDecryptStep(CKYAPDU *apdu, const void *param)
435 +{
436 + const CKYBuffer *buf=(CKYBuffer *)param;
437 + return CACAPDUFactory_SignDecrypt(apdu, CAC_P1_STEP, buf);
438 +}
439 +
440 +CKYStatus
441 +CACAppletFactory_SignDecryptFinal(CKYAPDU *apdu, const void *param)
442 {
443 const CKYBuffer *buf=(CKYBuffer *)param;
444 - return CACAPDUFactory_SignDecrypt(apdu, buf);
445 + return CACAPDUFactory_SignDecrypt(apdu, CAC_P1_FINAL, buf);
446 }
447
448 CKYStatus
449 @@ -246,6 +259,13 @@
450 }
451
452 CKYStatus
453 +CACAppletFactory_ReadFile(CKYAPDU *apdu, const void *param)
454 +{
455 + const CACAppletArgReadFile *rfs = (const CACAppletArgReadFile *)param;
456 + return CACAPDUFactory_ReadFile(apdu, rfs->offset, rfs->type, rfs->count);
457 +}
458 +
459 +CKYStatus
460 CACAppletFactory_GetProperties(CKYAPDU *apdu, const void *param)
461 {
462 return CACAPDUFactory_GetProperties(apdu);
463 @@ -457,7 +477,7 @@
464 CKYISOStatus *apduRC)
465 {
466 return CKYApplet_HandleAPDU(conn, CKYAppletFactory_SelectFile, AID, NULL,
467 - 0, CKYAppletFill_Null, NULL, apduRC);
468 + CKY_SIZE_UNKNOWN, CKYAppletFill_Null, NULL, apduRC);
469 }
470
471 static CKYByte coolkeyid[] = {0x62, 0x76, 0x01, 0xff, 0x00, 0x00, 0x00 };
472 @@ -477,22 +497,23 @@
473 return ret;
474 }
475
476 -static CKYByte CACPKIid[] = {0xa0, 0x00, 0x00, 0x00, 0x79, 0x01, 0x00 };
477 +static CKYByte CACPKIid[] = { 0xa0, 0x00, 0x00, 0x00, 0x79, 0x01 };
478 /*
479 * Select the CoolKey applet. Must happen after we start a transaction and
480 * before we issue any applet specific command.
481 */
482 CKYStatus
483 -CACApplet_SelectPKI(CKYCardConnection *conn, CKYByte instance,
484 - CKYISOStatus *apduRC)
485 +CACApplet_SelectPKI(CKYCardConnection *conn, CKYBuffer *cacAID,
486 + CKYByte instance, CKYISOStatus *apduRC)
487 {
488 CKYStatus ret;
489 - CKYBuffer CACPKIAID;
490 - CKYBuffer_InitFromData(&CACPKIAID, CACPKIid, sizeof(CACPKIid));
491 - CKYBuffer_SetChar(&CACPKIAID, 6, instance);
492 - ret = CKYApplet_HandleAPDU(conn, CKYAppletFactory_SelectFile, &CACPKIAID,
493 + CKYBuffer_AppendData(cacAID, CACPKIid, sizeof(CACPKIid));
494 + CKYBuffer_AppendChar(cacAID, instance);
495 + ret = CKYApplet_HandleAPDU(conn, CKYAppletFactory_SelectFile, cacAID,
496 NULL, CKY_SIZE_UNKNOWN, CKYAppletFill_Null, NULL, apduRC);
497 - CKYBuffer_FreeData(&CACPKIAID);
498 + if (ret != CKYSUCCESS) {
499 + CKYBuffer_Resize(cacAID, 0);
500 + }
501 return ret;
502 }
503
504 @@ -515,11 +536,38 @@
505 CKYBuffer CAC_CM_AID;
506 CKYBuffer_InitFromData(&CAC_CM_AID, cacmgrid, sizeof(cacmgrid));
507 ret = CKYApplet_HandleAPDU(conn, CKYAppletFactory_SelectFile, &CAC_CM_AID,
508 - NULL, 0, CKYAppletFill_Null, NULL, apduRC);
509 + NULL, CKY_SIZE_UNKNOWN, CKYAppletFill_Null, NULL, apduRC);
510 CKYBuffer_FreeData(&CAC_CM_AID);
511 return ret;
512 }
513
514 +static CKYByte cacCCCid[] = {0xa0, 0x00, 0x00, 0x01, 0x16, 0xdb, 0x00 };
515 +CKYStatus
516 +CACApplet_SelectCCC(CKYCardConnection *conn, CKYISOStatus *apduRC)
517 +{
518 + CKYStatus ret;
519 + CKYBuffer CAC_CM_AID;
520 + CKYBuffer_InitFromData(&CAC_CM_AID, cacCCCid, sizeof(cacCCCid));
521 + ret = CKYApplet_HandleAPDU(conn, CKYAppletFactory_SelectFile, &CAC_CM_AID,
522 + NULL, CKY_SIZE_UNKNOWN, CKYAppletFill_Null, NULL, apduRC);
523 + CKYBuffer_FreeData(&CAC_CM_AID);
524 + return ret;
525 +}
526 +
527 +CKYStatus
528 +CACApplet_SelectFile(CKYCardConnection *conn, unsigned short ef,
529 + CKYISOStatus *apduRC)
530 +{
531 + CKYStatus ret;
532 + CKYBuffer efBuf;
533 + CKYBuffer_InitEmpty(&efBuf);
534 + CKYBuffer_AppendShortLE(&efBuf, ef);
535 + ret = CKYApplet_HandleAPDU(conn, CACAppletFactory_SelectFile, &efBuf,
536 + NULL, CKY_SIZE_UNKNOWN, CKYAppletFill_Null, NULL, apduRC);
537 + CKYBuffer_FreeData(&efBuf);
538 + return ret;
539 +}
540 +
541 /*
542 * GetCPLC cluster -- must be called with CM selected
543 */
544 @@ -673,8 +721,8 @@
545 ccd.keyNumber = keyNumber;
546 ccd.location = location;
547 ccd.data = data;
548 - return CKYApplet_HandleAPDU(conn, CKYAppletFactory_ComputeCryptProcess, &ccd,
549 - nonce, 0, CKYAppletFill_Null, NULL, apduRC);
550 + return CKYApplet_HandleAPDU(conn, CKYAppletFactory_ComputeCryptProcess,
551 + &ccd, nonce, 0, CKYAppletFill_Null, NULL, apduRC);
552 }
553
554 /* computeCrypt returns data in the form :
555 @@ -832,11 +880,39 @@
556 CKYBuffer *result, CKYISOStatus *apduRC)
557 {
558 CKYStatus ret;
559 -
560 - ret = CKYApplet_HandleAPDU(conn,
561 - CACAppletFactory_SignDecrypt, data, NULL,
562 - CKYBuffer_Size(data), CKYAppletFill_ReplaceBuffer,
563 + CKYSize dataSize = CKYBuffer_Size(data);
564 + CKYOffset offset = 0;
565 + CKYBuffer tmp;
566 +
567 + CKYBuffer_InitEmpty(&tmp);
568 +
569 + CKYBuffer_Resize(result, 0);
570 + for(offset = 0; (dataSize-offset) > CKY_MAX_WRITE_CHUNK_SIZE;
571 + offset += CKY_MAX_WRITE_CHUNK_SIZE) {
572 + CKYBuffer_Resize(&tmp,0);
573 + CKYBuffer_AppendBuffer(&tmp, data, offset, CKY_MAX_WRITE_CHUNK_SIZE);
574 + ret = CKYApplet_HandleAPDU(conn, CACAppletFactory_SignDecryptStep,
575 + &tmp, NULL, CKY_SIZE_UNKNOWN,
576 + CKYAppletFill_AppendBuffer,
577 result, apduRC);
578 + if (ret != CKYSUCCESS) {
579 + goto done;
580 + }
581 + }
582 + CKYBuffer_Resize(&tmp,0);
583 + CKYBuffer_AppendBuffer(&tmp, data, offset, dataSize - offset);
584 + ret = CKYApplet_HandleAPDU(conn, CACAppletFactory_SignDecryptFinal,
585 + &tmp, NULL, CKY_SIZE_UNKNOWN,
586 + CKYAppletFill_AppendBuffer,
587 + result, apduRC);
588 +
589 + if ((ret == CKYSUCCESS) && (CKYBuffer_Size(result) != dataSize)) {
590 + /* RSA returns the same data size as input, didn't happen, so
591 + * something is wrong. */
592 + }
593 +
594 +done:
595 + CKYBuffer_FreeData(&tmp);
596 return ret;
597 }
598
599 @@ -895,6 +971,63 @@
600 }
601 return ret;
602 }
603 +
604 +/*
605 + * Read a CAC Tag/Value file
606 + */
607 +CKYStatus
608 +CACApplet_ReadFile(CKYCardConnection *conn, CKYByte type, CKYBuffer *buffer,
609 + CKYISOStatus *apduRC)
610 +{
611 + CKYStatus ret;
612 + CKYISOStatus status;
613 + CKYByte maxtransfer;
614 + unsigned short offset = 0;
615 + unsigned short size;
616 + CACAppletArgReadFile rfs;
617 +
618 + CKYBuffer_Resize(buffer,0);
619 + if (apduRC == NULL) {
620 + apduRC = &status;
621 + }
622 + rfs.offset = 0;
623 + rfs.count = 2;
624 + rfs.type = type;
625 +
626 + /* APDU's are expensive, Grab a big chunk of the file first if possible */
627 + ret = CKYApplet_HandleAPDU(conn,
628 + CACAppletFactory_ReadFile, &rfs, NULL,
629 + rfs.count, CKYAppletFill_AppendBuffer,
630 + buffer, apduRC);
631 + /* file is probably smaller than 100 bytes, get the actual size first */
632 + if (ret != CKYSUCCESS) {
633 + return ret;
634 + }
635 + size = CKYBuffer_GetShortLE(buffer, 0) + 2 /* include the length itself */;
636 + maxtransfer = CKY_MAX_READ_CHUNK_SIZE;
637 + /* get the rest of the buffer if necessary */
638 + for (offset = CKYBuffer_Size(buffer); size > offset;
639 + offset = CKYBuffer_Size(buffer)) {
640 + rfs.offset = offset;
641 + rfs.count = MIN(size - offset, maxtransfer);
642 + ret = CKYApplet_HandleAPDU(conn,
643 + CACAppletFactory_ReadFile, &rfs, NULL,
644 + rfs.count, CKYAppletFill_AppendBuffer,
645 + buffer, apduRC);
646 + if (ret != CKYSUCCESS) {
647 + if (*apduRC == CAC_INVALID_PARAMS) {
648 + maxtransfer = maxtransfer/2;
649 + if (maxtransfer == 0) {
650 + return ret;
651 + }
652 + } else {
653 + return ret;
654 + }
655 + }
656 + }
657 + return ret;
658 +}
659 +
660 CKYStatus
661 CACApplet_GetCertificateFirst(CKYCardConnection *conn, CKYBuffer *cert,
662 CKYSize *nextSize, CKYISOStatus *apduRC)
663 --- a/src/libckyapplet/cky_applet.h
664 +++ b/src/libckyapplet/cky_applet.h
665 @@ -71,6 +71,15 @@
666 #define CKYISO_INTERNAL_ERROR 0x9cff /* Reserved for debugging,
667 * shouldn't happen */
668
669 +#define CAC_INVALID_PARAMS 0x6a83
670 +#define CAC_TAG_FILE 1
671 +#define CAC_VALUE_FILE 2
672 +
673 +
674 +#define CAC_TAG_CARDURL 0xf3
675 +#define CAC_TAG_CERTIFICATE 0x70
676 +#define CAC_TLV_APP_PKI 0x04
677 +
678 /*
679 * Pin Constants as used by our applet
680 */
681 @@ -209,6 +218,12 @@
682 const CKYBuffer *sig;
683 } CKYAppletArgComputeCrypt;
684
685 +typedef struct _CACAppletArgReadFile {
686 + CKYByte type;
687 + CKYByte count;
688 + unsigned short offset;
689 +} CACAppletArgReadFile;
690 +
691 /* fills in an APDU from a structure -- form of all the generic factories*/
692 typedef CKYStatus (*CKYAppletFactory)(CKYAPDU *apdu, const void *param);
693 /* fills in an a structure from a response -- form of all the fill structures*/
694 @@ -451,9 +466,17 @@
695 /* Select the CAC card manager. Can happen with either applet selected */
696 CKYStatus CACApplet_SelectCardManager(CKYCardConnection *conn,
697 CKYISOStatus *apduRC);
698 -/* Can happen with either applet selected */
699 -CKYStatus CACApplet_SelectPKI(CKYCardConnection *conn, CKYByte instance,
700 - CKYISOStatus *apduRC);
701 +/* Select the CAC CC container. Can happen with either applet selected */
702 +CKYStatus CACApplet_SelectCCC(CKYCardConnection *conn, CKYISOStatus *apduRC);
703 +/* Select an old CAC applet and fill in the cardAID */
704 +CKYStatus CACApplet_SelectPKI(CKYCardConnection *conn, CKYBuffer *cardAid,
705 + CKYByte instance, CKYISOStatus *apduRC);
706 +/* read a TLV file */
707 +CKYStatus CACApplet_ReadFile(CKYCardConnection *conn, CKYByte type,
708 + CKYBuffer *buffer, CKYISOStatus *apduRC);
709 +CKYStatus CACApplet_SelectFile(CKYCardConnection *conn, unsigned short ef,
710 + CKYISOStatus *apduRC);
711 +
712 /* must happen with PKI applet selected */
713 CKYStatus CACApplet_SignDecrypt(CKYCardConnection *conn, const CKYBuffer *data,
714 CKYBuffer *result, CKYISOStatus *apduRC);
715 --- a/src/libckyapplet/cky_base.c
716 +++ b/src/libckyapplet/cky_base.c
717 @@ -220,6 +220,22 @@
718 return CKYSUCCESS;
719 }
720
721 +/* append a short in network order */
722 +CKYStatus
723 +CKYBuffer_AppendShortLE(CKYBuffer *buf, unsigned short val)
724 +{
725 + CKYStatus ret;
726 +
727 + ret = CKYBuffer_Reserve(buf, buf->len + 2);
728 + if (ret != CKYSUCCESS) {
729 + return ret;
730 + }
731 + buf->data[buf->len+1] = (CKYByte) ((val >> 8) & 0xff);
732 + buf->data[buf->len+0] = (CKYByte) ((val >> 0) & 0xff);
733 + buf->len += 2;
734 + return CKYSUCCESS;
735 +}
736 +
737 /* append a long in applet order */
738 CKYStatus
739 CKYBuffer_AppendLong(CKYBuffer *buf, unsigned long val)
740 @@ -238,6 +254,24 @@
741 return CKYSUCCESS;
742 }
743
744 +/* append a long in applet order */
745 +CKYStatus
746 +CKYBuffer_AppendLongLE(CKYBuffer *buf, unsigned long val)
747 +{
748 + CKYStatus ret;
749 +
750 + ret = CKYBuffer_Reserve(buf, buf->len + 4);
751 + if (ret != CKYSUCCESS) {
752 + return ret;
753 + }
754 + buf->data[buf->len+3] = (CKYByte) ((val >> 24) & 0xff);
755 + buf->data[buf->len+2] = (CKYByte) ((val >> 16) & 0xff);
756 + buf->data[buf->len+1] = (CKYByte) ((val >> 8) & 0xff);
757 + buf->data[buf->len+0] = (CKYByte) ((val >> 0) & 0xff);
758 + buf->len += 4;
759 + return CKYSUCCESS;
760 +}
761 +
762 CKYStatus
763 CKYBuffer_Replace(CKYBuffer *buf, CKYOffset offset, const CKYByte *data, CKYSize len)
764 {
765 @@ -351,6 +385,22 @@
766 }
767
768 CKYStatus
769 +CKYBuffer_SetShortLE(CKYBuffer *buf, CKYOffset offset, unsigned short val)
770 +{
771 + CKYStatus ret;
772 +
773 + if (buf->len < offset+2) {
774 + ret = CKYBuffer_Resize(buf,offset+2);
775 + if (ret != CKYSUCCESS) {
776 + return ret;
777 + }
778 + }
779 + buf->data[offset+1] = (CKYByte) ((val >> 8) & 0xff);
780 + buf->data[offset+0] = (CKYByte) ((val >> 0) & 0xff);
781 + return CKYSUCCESS;
782 +}
783 +
784 +CKYStatus
785 CKYBuffer_SetLong(CKYBuffer *buf, CKYOffset offset, unsigned long val)
786 {
787 CKYStatus ret;
788 @@ -368,6 +418,24 @@
789 return CKYSUCCESS;
790 }
791
792 +CKYStatus
793 +CKYBuffer_SetLongLE(CKYBuffer *buf, CKYOffset offset, unsigned long val)
794 +{
795 + CKYStatus ret;
796 +
797 + if (buf->len < offset+4) {
798 + ret = CKYBuffer_Resize(buf,offset+4);
799 + if (ret != CKYSUCCESS) {
800 + return ret;
801 + }
802 + }
803 + buf->data[offset+3] = (CKYByte) ((val >> 24) & 0xff);
804 + buf->data[offset+2] = (CKYByte) ((val >> 16) & 0xff);
805 + buf->data[offset+1] = (CKYByte) ((val >> 8) & 0xff);
806 + buf->data[offset+0] = (CKYByte) ((val >> 0) & 0xff);
807 + return CKYSUCCESS;
808 +}
809 +
810 CKYByte
811 CKYBuffer_GetChar(const CKYBuffer *buf, CKYOffset offset)
812 {
813 @@ -388,6 +456,18 @@
814 val |= ((unsigned short)buf->data[offset+1]) << 0;
815 return val;
816 }
817 +
818 +unsigned short
819 +CKYBuffer_GetShortLE(const CKYBuffer *buf, CKYOffset offset)
820 +{
821 + unsigned short val;
822 + if (buf->len < offset+2) {
823 + return 0;
824 + }
825 + val = ((unsigned short)buf->data[offset+1]) << 8;
826 + val |= ((unsigned short)buf->data[offset+0]) << 0;
827 + return val;
828 +}
829
830 unsigned long
831 CKYBuffer_GetLong(const CKYBuffer *buf, CKYOffset offset)
832 @@ -402,6 +482,20 @@
833 val |= ((unsigned long)buf->data[offset+3]) << 0;
834 return val;
835 }
836 +
837 +unsigned long
838 +CKYBuffer_GetLongLE(const CKYBuffer *buf, CKYOffset offset)
839 +{
840 + unsigned long val;
841 + if (buf->len < offset+4) {
842 + return 0;
843 + }
844 + val = ((unsigned long)buf->data[offset+3]) << 24;
845 + val |= ((unsigned long)buf->data[offset+2]) << 16;
846 + val |= ((unsigned long)buf->data[offset+1]) << 8;
847 + val |= ((unsigned long)buf->data[offset+0]) << 0;
848 + return val;
849 +}
850
851 CKYStatus
852 CKYBuffer_Resize(CKYBuffer *buf, CKYSize newLen)
853 --- a/src/libckyapplet/cky_base.h
854 +++ b/src/libckyapplet/cky_base.h
855 @@ -170,9 +170,15 @@
856 /* append a short in applet order */
857 CKYStatus CKYBuffer_AppendShort(CKYBuffer *buf, unsigned short val);
858
859 +/* append a short in little endian order */
860 +CKYStatus CKYBuffer_AppendShortLE(CKYBuffer *buf, unsigned short val);
861 +
862 /* append a long in applet order */
863 CKYStatus CKYBuffer_AppendLong(CKYBuffer *buf, unsigned long val);
864
865 +/* append a long in little endian order */
866 +CKYStatus CKYBuffer_AppendLongLE(CKYBuffer *buf, unsigned long val);
867 +
868 /* append data. the data starts at data and extends len bytes */
869 CKYStatus CKYBuffer_AppendData(CKYBuffer *buf, const CKYByte *data, CKYSize len);
870
871 @@ -210,12 +216,18 @@
872 CKYStatus CKYBuffer_SetShort(CKYBuffer *buf, CKYOffset offset, unsigned short val);
873 CKYStatus CKYBuffer_SetLong(CKYBuffer *buf, CKYOffset offset, unsigned long val);
874
875 +/* These functions work in little endian order */
876 +CKYStatus CKYBuffer_SetShortLE(CKYBuffer *buf, CKYOffset offset, unsigned short val);
877 +CKYStatus CKYBuffer_SetLongLE(CKYBuffer *buf, CKYOffset offset, unsigned long val);
878 /* read a character from offset. If offset is beyond the end of the buffer,
879 * then the function returns '0' */
880 CKYByte CKYBuffer_GetChar(const CKYBuffer *buf, CKYOffset offset);
881 /* These functions work in applet order */
882 unsigned short CKYBuffer_GetShort(const CKYBuffer *buf, CKYOffset offset);
883 unsigned long CKYBuffer_GetLong(const CKYBuffer *buf, CKYOffset offset);
884 +/* These functions work in little endian order */
885 +unsigned short CKYBuffer_GetShortLE(const CKYBuffer *buf, CKYOffset offset);
886 +unsigned long CKYBuffer_GetLongLE(const CKYBuffer *buf, CKYOffset offset);
887
888 /* clear out all the data in a buffer */
889 void CKYBuffer_Zero(CKYBuffer *buf);
890 --- a/src/libckyapplet/cky_factory.c
891 +++ b/src/libckyapplet/cky_factory.c
892 @@ -25,12 +25,13 @@
893 * special commands can be issued at any time
894 */
895 CKYStatus
896 -CKYAPDUFactory_SelectFile(CKYAPDU *apdu, const CKYBuffer *AID)
897 +CKYAPDUFactory_SelectFile(CKYAPDU *apdu, CKYByte p1, CKYByte p2,
898 + const CKYBuffer *AID)
899 {
900 CKYAPDU_SetCLA(apdu, CKY_CLASS_ISO7816);
901 CKYAPDU_SetINS(apdu, CKY_INS_SELECT_FILE);
902 - CKYAPDU_SetP1(apdu, 0x04);
903 - CKYAPDU_SetP2(apdu, 0x00);
904 + CKYAPDU_SetP1(apdu, p1);
905 + CKYAPDU_SetP2(apdu, p2);
906 return CKYAPDU_SetSendDataBuffer(apdu, AID);
907 }
908
909 @@ -131,6 +132,7 @@
910 return ret;
911 }
912
913 +
914 CKYStatus
915 CKYAPDUFactory_ComputeCryptFinal(CKYAPDU *apdu, CKYByte keyNumber,
916 CKYByte location, const CKYBuffer *data, const CKYBuffer *sig)
917 @@ -572,11 +574,11 @@
918 }
919
920 CKYStatus
921 -CACAPDUFactory_SignDecrypt(CKYAPDU *apdu, const CKYBuffer *data)
922 +CACAPDUFactory_SignDecrypt(CKYAPDU *apdu, CKYByte type, const CKYBuffer *data)
923 {
924 CKYAPDU_SetCLA(apdu, CKY_CLASS_ISO7816);
925 CKYAPDU_SetINS(apdu, CAC_INS_SIGN_DECRYPT);
926 - CKYAPDU_SetP1(apdu, 0x00);
927 + CKYAPDU_SetP1(apdu, type);
928 CKYAPDU_SetP2(apdu, 0x00);
929 return CKYAPDU_SetSendDataBuffer(apdu, data);
930 }
931 @@ -592,6 +594,36 @@
932 }
933
934 CKYStatus
935 +CACAPDUFactory_ReadFile(CKYAPDU *apdu, unsigned short offset,
936 + CKYByte type, CKYByte count)
937 +{
938 + CKYStatus ret;
939 + CKYBuffer buf;
940 +
941 + CKYBuffer_InitEmpty(&buf);
942 + CKYAPDU_SetCLA(apdu, CKY_CLASS_GLOBAL_PLATFORM);
943 + CKYAPDU_SetINS(apdu, CAC_INS_READ_FILE);
944 + CKYAPDU_SetP1(apdu, (offset >> 8) & 0xff);
945 + CKYAPDU_SetP2(apdu, offset & 0xff);
946 + ret = CKYBuffer_Reserve(&buf, 2);
947 + if (ret != CKYSUCCESS) {
948 + goto fail;
949 + }
950 + ret = CKYBuffer_AppendChar(&buf, type);
951 + if (ret != CKYSUCCESS) {
952 + goto fail;
953 + }
954 + ret = CKYBuffer_AppendChar(&buf, count);
955 + if (ret != CKYSUCCESS) {
956 + goto fail;
957 + }
958 + ret = CKYAPDU_SetSendDataBuffer(apdu, &buf);
959 +fail:
960 + CKYBuffer_FreeData(&buf);
961 + return ret;
962 +}
963 +
964 +CKYStatus
965 CACAPDUFactory_GetProperties(CKYAPDU *apdu)
966 {
967 CKYAPDU_SetCLA(apdu, CKY_CLASS_ISO7816);
968 --- a/src/libckyapplet/cky_factory.h
969 +++ b/src/libckyapplet/cky_factory.h
970 @@ -86,7 +86,11 @@
971 #define CAC_INS_SIGN_DECRYPT 0x42
972 #define CAC_INS_VERIFY_PIN 0x20
973 #define CAC_INS_GET_PROPERTIES 0x56
974 +#define CAC_INS_READ_FILE 0x52
975 +
976 #define CAC_SIZE_GET_PROPERTIES 48
977 +#define CAC_P1_STEP 0x80
978 +#define CAC_P1_FINAL 0x00
979
980 /*
981 * Fixed return sized from various commands
982 @@ -169,7 +173,8 @@
983 CKY_BEGIN_PROTOS
984
985 /* function based factorys */
986 -CKYStatus CKYAPDUFactory_SelectFile(CKYAPDU *apdu, const CKYBuffer *AID);
987 +CKYStatus CKYAPDUFactory_SelectFile(CKYAPDU *apdu, CKYByte p1, CKYByte p2,
988 + const CKYBuffer *AID);
989 CKYStatus CKYAPDUFactory_SelectCardManager(CKYAPDU *apdu);
990 CKYStatus CKYAPDUFactory_GetCPLCData(CKYAPDU *apdu);
991 CKYStatus CKYAPDUFactory_ListKeys(CKYAPDU *apdu, CKYByte sequence);
992 @@ -211,9 +216,12 @@
993 CKYStatus CKYAPDUFactory_GetIssuerInfo(CKYAPDU *apdu);
994 CKYStatus CKYAPDUFactory_GetBuiltinACL(CKYAPDU *apdu);
995
996 -CKYStatus CACAPDUFactory_SignDecrypt(CKYAPDU *apdu, const CKYBuffer *data);
997 +CKYStatus CACAPDUFactory_SignDecrypt(CKYAPDU *apdu, CKYByte type,
998 + const CKYBuffer *data);
999 CKYStatus CACAPDUFactory_VerifyPIN(CKYAPDU *apdu, const char *pin);
1000 CKYStatus CACAPDUFactory_GetCertificate(CKYAPDU *apdu, CKYSize size);
1001 +CKYStatus CACAPDUFactory_ReadFile(CKYAPDU *apdu, unsigned short offset,
1002 + CKYByte type, CKYByte count);
1003 CKYStatus CACAPDUFactory_GetProperties(CKYAPDU *apdu);
1004
1005 CKY_END_PROTOS

  ViewVC Help
Powered by ViewVC 1.1.5