/[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 - (hide 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 bottoms 60 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 bottoms 39 --- 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