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

  ViewVC Help
Powered by ViewVC 1.1.5