These changes are a raw update to a vanilla kernel 4.1.10, with the
[kvmfornfv.git] / qemu / libcacard / cac.c
1 /*
2  * implement the applets for the CAC card.
3  *
4  * This code is licensed under the GNU LGPL, version 2.1 or later.
5  * See the COPYING.LIB file in the top-level directory.
6  */
7
8 #include "glib-compat.h"
9
10 #include <string.h>
11 #include <stdbool.h>
12
13 #include "cac.h"
14 #include "vcard.h"
15 #include "vcard_emul.h"
16 #include "card_7816.h"
17
18 /* private data for PKI applets */
19 typedef struct CACPKIAppletDataStruct {
20     unsigned char *cert;
21     int cert_len;
22     unsigned char *cert_buffer;
23     int cert_buffer_len;
24     unsigned char *sign_buffer;
25     int sign_buffer_len;
26     VCardKey *key;
27 } CACPKIAppletData;
28
29 /*
30  * CAC applet private data
31  */
32 struct VCardAppletPrivateStruct {
33     union {
34         CACPKIAppletData pki_data;
35         void *reserved;
36     } u;
37 };
38
39 /*
40  * handle all the APDU's that are common to all CAC applets
41  */
42 static VCardStatus
43 cac_common_process_apdu(VCard *card, VCardAPDU *apdu, VCardResponse **response)
44 {
45     int ef;
46     VCardStatus ret = VCARD_FAIL;
47
48     switch (apdu->a_ins) {
49     case VCARD7816_INS_SELECT_FILE:
50         if (apdu->a_p1 != 0x02) {
51             /* let the 7816 code handle applet switches */
52             ret = VCARD_NEXT;
53             break;
54         }
55         /* handle file id setting */
56         if (apdu->a_Lc != 2) {
57             *response = vcard_make_response(
58                 VCARD7816_STATUS_ERROR_DATA_INVALID);
59             ret = VCARD_DONE;
60             break;
61         }
62         /* CAC 1.0 only supports ef = 0 */
63         ef = apdu->a_body[0] | (apdu->a_body[1] << 8);
64         if (ef != 0) {
65             *response = vcard_make_response(
66                 VCARD7816_STATUS_ERROR_FILE_NOT_FOUND);
67             ret = VCARD_DONE;
68             break;
69         }
70         *response = vcard_make_response(VCARD7816_STATUS_SUCCESS);
71         ret = VCARD_DONE;
72         break;
73     case VCARD7816_INS_GET_RESPONSE:
74     case VCARD7816_INS_VERIFY:
75         /* let the 7816 code handle these */
76         ret = VCARD_NEXT;
77         break;
78     case CAC_GET_PROPERTIES:
79     case CAC_GET_ACR:
80         /* skip these for now, this will probably be needed */
81         *response = vcard_make_response(VCARD7816_STATUS_ERROR_P1_P2_INCORRECT);
82         ret = VCARD_DONE;
83         break;
84     default:
85         *response = vcard_make_response(
86             VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
87         ret = VCARD_DONE;
88         break;
89     }
90     return ret;
91 }
92
93 /*
94  *  reset the inter call state between applet selects
95  */
96 static VCardStatus
97 cac_applet_pki_reset(VCard *card, int channel)
98 {
99     VCardAppletPrivate *applet_private;
100     CACPKIAppletData *pki_applet;
101     applet_private = vcard_get_current_applet_private(card, channel);
102     assert(applet_private);
103     pki_applet = &(applet_private->u.pki_data);
104
105     pki_applet->cert_buffer = NULL;
106     g_free(pki_applet->sign_buffer);
107     pki_applet->sign_buffer = NULL;
108     pki_applet->cert_buffer_len = 0;
109     pki_applet->sign_buffer_len = 0;
110     return VCARD_DONE;
111 }
112
113 static VCardStatus
114 cac_applet_pki_process_apdu(VCard *card, VCardAPDU *apdu,
115                             VCardResponse **response)
116 {
117     CACPKIAppletData *pki_applet;
118     VCardAppletPrivate *applet_private;
119     int size, next;
120     unsigned char *sign_buffer;
121     bool retain_sign_buffer = FALSE;
122     vcard_7816_status_t status;
123     VCardStatus ret = VCARD_FAIL;
124
125     applet_private = vcard_get_current_applet_private(card, apdu->a_channel);
126     assert(applet_private);
127     pki_applet = &(applet_private->u.pki_data);
128
129     switch (apdu->a_ins) {
130     case CAC_UPDATE_BUFFER:
131         *response = vcard_make_response(
132             VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED);
133         ret = VCARD_DONE;
134         break;
135     case CAC_GET_CERTIFICATE:
136         if ((apdu->a_p2 != 0) || (apdu->a_p1 != 0)) {
137             *response = vcard_make_response(
138                              VCARD7816_STATUS_ERROR_P1_P2_INCORRECT);
139             break;
140         }
141         assert(pki_applet->cert != NULL);
142         size = apdu->a_Le;
143         if (pki_applet->cert_buffer == NULL) {
144             pki_applet->cert_buffer = pki_applet->cert;
145             pki_applet->cert_buffer_len = pki_applet->cert_len;
146         }
147         size = MIN(size, pki_applet->cert_buffer_len);
148         next = MIN(255, pki_applet->cert_buffer_len - size);
149         *response = vcard_response_new_bytes(
150                         card, pki_applet->cert_buffer, size,
151                         apdu->a_Le, next ?
152                         VCARD7816_SW1_WARNING_CHANGE :
153                         VCARD7816_SW1_SUCCESS,
154                         next);
155         pki_applet->cert_buffer += size;
156         pki_applet->cert_buffer_len -= size;
157         if ((*response == NULL) || (next == 0)) {
158             pki_applet->cert_buffer = NULL;
159         }
160         if (*response == NULL) {
161             *response = vcard_make_response(
162                             VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
163         }
164         ret = VCARD_DONE;
165         break;
166     case CAC_SIGN_DECRYPT:
167         if (apdu->a_p2 != 0) {
168             *response = vcard_make_response(
169                              VCARD7816_STATUS_ERROR_P1_P2_INCORRECT);
170             break;
171         }
172         size = apdu->a_Lc;
173
174         sign_buffer = g_realloc(pki_applet->sign_buffer,
175                                 pki_applet->sign_buffer_len + size);
176         memcpy(sign_buffer+pki_applet->sign_buffer_len, apdu->a_body, size);
177         size += pki_applet->sign_buffer_len;
178         switch (apdu->a_p1) {
179         case  0x80:
180             /* p1 == 0x80 means we haven't yet sent the whole buffer, wait for
181              * the rest */
182             pki_applet->sign_buffer = sign_buffer;
183             pki_applet->sign_buffer_len = size;
184             *response = vcard_make_response(VCARD7816_STATUS_SUCCESS);
185             retain_sign_buffer = TRUE;
186             break;
187         case 0x00:
188             /* we now have the whole buffer, do the operation, result will be
189              * in the sign_buffer */
190             status = vcard_emul_rsa_op(card, pki_applet->key,
191                                        sign_buffer, size);
192             if (status != VCARD7816_STATUS_SUCCESS) {
193                 *response = vcard_make_response(status);
194                 break;
195             }
196             *response = vcard_response_new(card, sign_buffer, size, apdu->a_Le,
197                                                      VCARD7816_STATUS_SUCCESS);
198             if (*response == NULL) {
199                 *response = vcard_make_response(
200                                 VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
201             }
202             break;
203         default:
204            *response = vcard_make_response(
205                                 VCARD7816_STATUS_ERROR_P1_P2_INCORRECT);
206             break;
207         }
208         if (!retain_sign_buffer) {
209             g_free(sign_buffer);
210             pki_applet->sign_buffer = NULL;
211             pki_applet->sign_buffer_len = 0;
212         }
213         ret = VCARD_DONE;
214         break;
215     case CAC_READ_BUFFER:
216         /* new CAC call, go ahead and use the old version for now */
217         /* TODO: implement */
218         *response = vcard_make_response(
219                                 VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
220         ret = VCARD_DONE;
221         break;
222     default:
223         ret = cac_common_process_apdu(card, apdu, response);
224         break;
225     }
226     return ret;
227 }
228
229
230 static VCardStatus
231 cac_applet_id_process_apdu(VCard *card, VCardAPDU *apdu,
232                            VCardResponse **response)
233 {
234     VCardStatus ret = VCARD_FAIL;
235
236     switch (apdu->a_ins) {
237     case CAC_UPDATE_BUFFER:
238         *response = vcard_make_response(
239                         VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED);
240         ret = VCARD_DONE;
241         break;
242     case CAC_READ_BUFFER:
243         /* new CAC call, go ahead and use the old version for now */
244         /* TODO: implement */
245         *response = vcard_make_response(
246                         VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
247         ret = VCARD_DONE;
248         break;
249     default:
250         ret = cac_common_process_apdu(card, apdu, response);
251         break;
252     }
253     return ret;
254 }
255
256
257 /*
258  * TODO: if we ever want to support general CAC middleware, we will need to
259  * implement the various containers.
260  */
261 static VCardStatus
262 cac_applet_container_process_apdu(VCard *card, VCardAPDU *apdu,
263                                   VCardResponse **response)
264 {
265     VCardStatus ret = VCARD_FAIL;
266
267     switch (apdu->a_ins) {
268     case CAC_READ_BUFFER:
269     case CAC_UPDATE_BUFFER:
270         *response = vcard_make_response(
271                         VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
272         ret = VCARD_DONE;
273         break;
274     default:
275         ret = cac_common_process_apdu(card, apdu, response);
276         break;
277     }
278     return ret;
279 }
280
281 /*
282  * utilities for creating and destroying the private applet data
283  */
284 static void
285 cac_delete_pki_applet_private(VCardAppletPrivate *applet_private)
286 {
287     CACPKIAppletData *pki_applet_data;
288
289     if (applet_private == NULL) {
290         return;
291     }
292     pki_applet_data = &(applet_private->u.pki_data);
293     g_free(pki_applet_data->cert);
294     g_free(pki_applet_data->sign_buffer);
295     if (pki_applet_data->key != NULL) {
296         vcard_emul_delete_key(pki_applet_data->key);
297     }
298     g_free(applet_private);
299 }
300
301 static VCardAppletPrivate *
302 cac_new_pki_applet_private(const unsigned char *cert,
303                            int cert_len, VCardKey *key)
304 {
305     CACPKIAppletData *pki_applet_data;
306     VCardAppletPrivate *applet_private;
307
308     applet_private = g_new0(VCardAppletPrivate, 1);
309     pki_applet_data = &(applet_private->u.pki_data);
310     pki_applet_data->cert = (unsigned char *)g_malloc(cert_len+1);
311     /*
312      * if we want to support compression, then we simply change the 0 to a 1
313      * and compress the cert data with libz
314      */
315     pki_applet_data->cert[0] = 0; /* not compressed */
316     memcpy(&pki_applet_data->cert[1], cert, cert_len);
317     pki_applet_data->cert_len = cert_len+1;
318
319     pki_applet_data->key = key;
320     return applet_private;
321 }
322
323
324 /*
325  * create a new cac applet which links to a given cert
326  */
327 static VCardApplet *
328 cac_new_pki_applet(int i, const unsigned char *cert,
329                    int cert_len, VCardKey *key)
330 {
331     VCardAppletPrivate *applet_private;
332     VCardApplet *applet;
333     unsigned char pki_aid[] = { 0xa0, 0x00, 0x00, 0x00, 0x79, 0x01, 0x00 };
334     int pki_aid_len = sizeof(pki_aid);
335
336     pki_aid[pki_aid_len-1] = i;
337
338     applet_private = cac_new_pki_applet_private(cert, cert_len, key);
339     if (applet_private == NULL) {
340         goto failure;
341     }
342     applet = vcard_new_applet(cac_applet_pki_process_apdu, cac_applet_pki_reset,
343                               pki_aid, pki_aid_len);
344     if (applet == NULL) {
345         goto failure;
346     }
347     vcard_set_applet_private(applet, applet_private,
348                              cac_delete_pki_applet_private);
349     applet_private = NULL;
350
351     return applet;
352
353 failure:
354     if (applet_private != NULL) {
355         cac_delete_pki_applet_private(applet_private);
356     }
357     return NULL;
358 }
359
360
361 static unsigned char cac_default_container_aid[] = {
362     0xa0, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00 };
363 static unsigned char cac_id_aid[] = {
364     0xa0, 0x00, 0x00, 0x00, 0x79, 0x03, 0x00 };
365 /*
366  * Initialize the cac card. This is the only public function in this file. All
367  * the rest are connected through function pointers.
368  */
369 VCardStatus
370 cac_card_init(VReader *reader, VCard *card,
371               const char *params,
372               unsigned char * const *cert,
373               int cert_len[],
374               VCardKey *key[] /* adopt the keys*/,
375               int cert_count)
376 {
377     int i;
378     VCardApplet *applet;
379
380     /* CAC Cards are VM Cards */
381     vcard_set_type(card, VCARD_VM);
382
383     /* create one PKI applet for each cert */
384     for (i = 0; i < cert_count; i++) {
385         applet = cac_new_pki_applet(i, cert[i], cert_len[i], key[i]);
386         if (applet == NULL) {
387             goto failure;
388         }
389         vcard_add_applet(card, applet);
390     }
391
392     /* create a default blank container applet */
393     applet = vcard_new_applet(cac_applet_container_process_apdu,
394                               NULL, cac_default_container_aid,
395                               sizeof(cac_default_container_aid));
396     if (applet == NULL) {
397         goto failure;
398     }
399     vcard_add_applet(card, applet);
400
401     /* create a default blank container applet */
402     applet = vcard_new_applet(cac_applet_id_process_apdu,
403                               NULL, cac_id_aid,
404                               sizeof(cac_id_aid));
405     if (applet == NULL) {
406         goto failure;
407     }
408     vcard_add_applet(card, applet);
409     return VCARD_DONE;
410
411 failure:
412     return VCARD_FAIL;
413 }
414