1 /* -*- mode: c; c-file-style:"stroustrup"; -*- */
2 
3 /*
4  * Copyright (c) 2018 Mastercard
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *   http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 #include <config.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <stdbool.h>
24 #include <ctype.h>
25 #include <time.h>
26 #include <unistd.h>
27 #include <search.h>
28 
29 #include <openssl/bio.h>
30 #include <openssl/pem.h>
31 #include <openssl/x509.h>
32 
33 #include "pkcs11lib.h"
34 #include "wrappedkey_lexer.h"
35 #include "wrappedkey_parser.h"
36 
37 #define INDENTATION_OFFSET 4
38 
39 typedef enum  {
40     meth_label,
41     meth_keyhandle
42 } wrap_source_method_t;
43 
44 typedef struct {
45     CK_ATTRIBUTE_TYPE attr_type;
46     void (*func_ptr) (FILE *, char *, CK_ATTRIBUTE_PTR, bool, int);
47     char *name;
48     bool commented;
49 } attr_printer ;
50 
51 
52 /* private funcs prototypes */
53 static char const *_get_str_for_wrapping_algorithm(enum wrappingmethod w, CK_MECHANISM_TYPE m);
54 static char const *get_wrapping_algorithm_short(wrappedKeyCtx *wctx);
55 static func_rc fprintf_wrapping_algorithm_full(FILE *fp, wrappedKeyCtx *wctx, char *buffer, size_t buffer_len, int keyindex);
56 static void fprintf_template_attr_member(FILE *fp, CK_ATTRIBUTE_PTR attr, int offset);
57 
58 static void fprintf_key_type(FILE *fp, char *unused, CK_ATTRIBUTE_PTR attr, bool unused2, int offset);
59 static void fprintf_object_class(FILE *fp, char *unused, CK_ATTRIBUTE_PTR attr, bool unused2, int offset);
60 static void fprintf_boolean_attr(FILE *fp, char *name, CK_ATTRIBUTE_PTR attr, bool commented, int offset);
61 static void fprintf_hex_attr(FILE *fp, char *name, CK_ATTRIBUTE_PTR attr, bool commented, int offset);
62 static void _fprintf_str_attr(FILE *fp, char *name, CK_ATTRIBUTE_PTR attr, bool commented, int offset);
63 static void fprintf_str_attr(FILE *fp, char *name, CK_ATTRIBUTE_PTR attr, bool commented, int offset);
64 static void fprintf_date_attr(FILE *fp, char *name, CK_ATTRIBUTE_PTR attr, bool commented, int offset);
65 static void fprintf_template_attr(FILE *fp, char *name, CK_ATTRIBUTE_PTR attr, bool commented, int offset);
66 static void fprintf_mechanism_type_array(FILE *fp, char *name, CK_ATTRIBUTE_PTR attr, bool commented, int offset);
67 
68 static char * sprintf_hex_buffer(CK_BYTE_PTR buffer, CK_ULONG len);
69 static char * _sprintf_str_buffer(CK_BYTE_PTR buffer, CK_ULONG len);
70 static char * sprintf_str_buffer_safe(CK_BYTE_PTR buffer, CK_ULONG len);
71 static void free_sprintf_str_buffer_safe_buf(char *ptr);
72 static char * const _mgfstring(CK_RSA_PKCS_MGF_TYPE mgf);
73 static char * const _hashstring(CK_MECHANISM_TYPE hash);
74 
75 static func_rc _output_wrapped_key_header(wrappedKeyCtx *wctx, FILE *fp);
76 static func_rc _output_wrapped_key_attributes(wrappedKeyCtx *wctx, FILE *fp);
77 static func_rc _output_wrapped_keys_b64(wrappedKeyCtx *wctx, FILE *fp);
78 static func_rc _output_public_key_attributes(wrappedKeyCtx *wctx, FILE *fp);
79 static func_rc _output_public_key_b64(wrappedKeyCtx *wctx, FILE *fp);
80 
81 static func_rc _wrap_aes_key_wrap_mech(wrappedKeyCtx *wctx, CK_MECHANISM_TYPE mech[], CK_ULONG mech_size);
82 static func_rc _wrap_rfc3394(wrappedKeyCtx *wctx);
83 static func_rc _wrap_rfc5649(wrappedKeyCtx *wctx);
84 static func_rc _wrap_pkcs1_15(wrappedKeyCtx *wctx);
85 static func_rc _wrap_pkcs1_oaep(wrappedKeyCtx *wctx);
86 static func_rc _wrap_cbcpad(wrappedKeyCtx *wctx);
87 static func_rc _wrap_envelope(wrappedKeyCtx *wctx);
88 
_wrap_rfc3394(wrappedKeyCtx * wctx)89 static inline func_rc _wrap_rfc3394(wrappedKeyCtx *wctx)
90 {
91     return _wrap_aes_key_wrap_mech(wctx, wctx->p11Context->rfc3394_mech, wctx->p11Context->rfc3394_mech_size);
92 }
93 
_wrap_rfc5649(wrappedKeyCtx * wctx)94 static inline func_rc _wrap_rfc5649(wrappedKeyCtx *wctx)
95 {
96     return _wrap_aes_key_wrap_mech(wctx, wctx->p11Context->rfc5649_mech, wctx->p11Context->rfc5649_mech_size);
97 }
98 
99 static func_rc _wrap(wrappedKeyCtx *wctx,
100 		     wrap_source_method_t wrap_source_method,
101 		     char *wrappedkeylabel,
102 		     CK_OBJECT_HANDLE wrappedkeyhandle,
103 		     CK_OBJECT_HANDLE pubkhandle);
104 
pkcs11_wrap_from_label(wrappedKeyCtx * wctx,char * wrappedkeylabel)105 inline func_rc pkcs11_wrap_from_label(wrappedKeyCtx *wctx, char *wrappedkeylabel)
106 {
107     return _wrap(wctx, meth_label, wrappedkeylabel, 0, 0);
108 }
109 
pkcs11_wrap_from_handle(wrappedKeyCtx * wctx,CK_OBJECT_HANDLE wrappedkeyhandle,CK_OBJECT_HANDLE pubkhandle)110 inline func_rc pkcs11_wrap_from_handle(wrappedKeyCtx *wctx, CK_OBJECT_HANDLE wrappedkeyhandle, CK_OBJECT_HANDLE pubkhandle)
111 {
112     return _wrap(wctx, meth_keyhandle, NULL, wrappedkeyhandle, pubkhandle);
113 }
114 
115 
_get_str_for_wrapping_algorithm(enum wrappingmethod w,CK_MECHANISM_TYPE m)116 static char const *_get_str_for_wrapping_algorithm(enum wrappingmethod w, CK_MECHANISM_TYPE m)
117 {
118     char *rc;
119     switch(w) {
120     case w_pkcs1_15:
121 	rc = "PKCS#1 1.5";
122 	break;
123 
124     case w_pkcs1_oaep:
125 	rc = "PKCS#1 OAEP";
126 	break;
127 
128     case w_cbcpad:
129 	rc = "PKCS#11 CKM_xxx_CBC_PAD, with PKCS#7 padding";
130 	break;
131 
132     case w_rfc3394:
133 	switch(m) {
134 	case CKM_AES_KEY_WRAP:
135 	    rc = "PKCS#11 CKM_AES_KEY_WRAP (RFC3394)";
136 	    break;
137 
138 	case CKM_NSS_AES_KEY_WRAP:
139 	    rc = "NSS CKM_NSS_AES_KEY_WRAP (RFC3394)";
140 	    break;
141 
142 #if defined(HAVE_LUNA)
143 	case CKM_LUNA_AES_KW:
144 	    rc = "Gemalto Safenet Luna CKM_AES_KW (RFC3394)";
145 	    break;
146 #endif
147 
148 	default:
149 	    rc = "Unknown???";
150 	}
151 	break;
152 
153     case w_rfc5649:
154 	switch(m) {
155 	case CKM_AES_KEY_WRAP_PAD:
156 	    rc = "PKCS#11 v2.40 CKM_AES_KEY_WRAP_PAD (RFC5649)";
157 	    break;
158 
159 	case CKM_NSS_AES_KEY_WRAP_PAD:
160 	    rc = "NSS CKM_NSS_AES_KEY_WRAP_PAD (!!<>RFC5649)";
161 	    break;
162 
163 #if defined(HAVE_LUNA)
164 	case CKM_LUNA_AES_KWP:
165 	    rc = "Gemalto Safenet Luna CKM_AES_KWP (RFC5649)";
166 	    break;
167 #endif
168 
169 	default:
170 	    rc = "Unknown???";
171 	}
172 	break;
173 
174     default:
175 	rc = "Unknown???";
176     }
177 
178     return rc;
179 }
180 
get_wrapping_algorithm_short(wrappedKeyCtx * wctx)181 static char const *get_wrapping_algorithm_short(wrappedKeyCtx *wctx)
182 {
183     if(wctx->is_envelope) {
184 	return "Envelope";	/* TODO: recursive content */
185     } else {
186 	return _get_str_for_wrapping_algorithm(wctx->key[WRAPPEDKEYCTX_LONE_KEY_INDEX].wrapping_meth, wctx->aes_params.aes_wrapping_mech);
187     }
188 }
189 
fprintf_wrapping_algorithm_full(FILE * fp,wrappedKeyCtx * wctx,char * buffer,size_t buffer_len,int keyindex)190 static func_rc fprintf_wrapping_algorithm_full(FILE *fp, wrappedKeyCtx *wctx, char *buffer, size_t buffer_len, int keyindex)
191 {
192 
193     func_rc rc;
194     /* when fp is non null, we try to write to the file system. Otherwise, it means we are re-entered recursively */
195     /* in which case we fill the received buffer */
196 
197     if(fp) {
198 	if(wctx->is_envelope) {
199 	    char inner[256];
200 	    char outer[256];
201 
202 	    rc = fprintf_wrapping_algorithm_full(NULL, wctx, inner, sizeof inner, WRAPPEDKEYCTX_INNER_KEY_INDEX);
203 	    if(rc!=rc_ok) { return rc;  }
204 	    rc = fprintf_wrapping_algorithm_full(NULL, wctx, outer, sizeof outer, WRAPPEDKEYCTX_OUTER_KEY_INDEX);
205 	    if(rc!=rc_ok) { return rc;  }
206 	    fprintf(fp, "Wrapping-Algorithm: %s/1.0(inner=%s,outer=%s)\n", "envelope", inner, outer);
207 	} else {		/* standalone */
208 	    char alone[256];
209 
210 	    if( (rc = fprintf_wrapping_algorithm_full(NULL, wctx, alone, sizeof alone, WRAPPEDKEYCTX_LONE_KEY_INDEX )) != rc_ok ) {
211 		return rc;
212 	    } /* exit prematurely */
213 	    fprintf(fp, "Wrapping-Algorithm: %s\n", alone );
214 	}
215     } else {
216 	/* we have re-entered the function and need to deal with actual algoritm. We use snprintf here */
217 	switch(wctx->key[keyindex].wrapping_meth) {
218 	case w_pkcs1_15:
219 	    snprintf(buffer, buffer_len, "%s/1.0", "pkcs1");
220 	    break;
221 
222 	    /* we have one additional parameter for oaep: the label (in PKCS#1), referred as source in PKCS#11 */
223 	case w_pkcs1_oaep: {
224 	    int nchar;
225 	    char *labelstring=sprintf_str_buffer_safe( wctx->oaep_params->pSourceData, wctx->oaep_params->ulSourceDataLen);
226 
227 	    nchar = snprintf(buffer,
228 			     buffer_len,
229 			     "%s/1.0(hash=%s,mgf=%s,label=%s)",
230 			     "oaep",
231 			     _hashstring(wctx->oaep_params->hashAlg),
232 			     _mgfstring(wctx->oaep_params->mgf),
233 			     wctx->oaep_params->pSourceData==NULL ? "\"\"" : labelstring );
234 
235 	    free_sprintf_str_buffer_safe_buf(labelstring);
236 
237 	    if(nchar>=buffer_len) {
238 		fprintf(stderr, "Error: algorithm string (%d) too long for buffer size (%zu)\n", nchar, buffer_len);
239 		return rc_error_memory;
240 	    }
241 	}
242 	    break;
243 
244 	case w_cbcpad:	{
245 	    char *labelstring=sprintf_str_buffer_safe( wctx->aes_params.iv, wctx->aes_params.iv_len );
246 
247 	    snprintf(buffer,
248 		     buffer_len,
249 		     "%s/1.0(iv=%s)",
250 		     "cbcpad",
251 		     labelstring );
252 
253 	    free_sprintf_str_buffer_safe_buf(labelstring);
254 	}
255 	    break;
256 
257 	case w_rfc3394:
258 	    snprintf(buffer,
259 		     buffer_len,
260 		     "%s/1.0",
261 		     "rfc3394");
262 	    break;
263 
264 	case w_rfc5649:
265 	    /* Because CKM_NSS_AES_KEY_WRAP_PAD is NOT fully compliant with RFC5649, */
266 	    /* we want to flag it as is, to prevent hairy cases when someone */
267 	    /* wants to unwrap it on a true RFC5649 compliant token */
268 	    snprintf(buffer,
269 		     buffer_len,
270 		     "%s/1.0%s",
271 		     "rfc5649",
272 		     wctx->aes_params.aes_wrapping_mech==CKM_NSS_AES_KEY_WRAP_PAD ? "(flavour=nss)" : "");
273 	    break;
274 
275 	default:
276 	    fprintf(stderr, "Error: unsupported wrapping algorithm.\n");
277 	    return rc_error_unknown_wrapping_alg;
278 	}
279     }
280     return rc_ok;
281 }
282 
283 
284 
285 
fprintf_key_type(FILE * fp,char * unused,CK_ATTRIBUTE_PTR attr,bool unused2,int offset)286 static void fprintf_key_type(FILE *fp, char *unused, CK_ATTRIBUTE_PTR attr, bool unused2, int offset)
287 {
288 
289     char *value;
290     switch( *(CK_KEY_TYPE *)attr->pValue) {
291 
292     case CKK_GENERIC_SECRET:
293 	value = "CKK_GENERIC_SECRET";
294 	break;
295 
296     case CKK_DES:
297 	value = "CKK_DES";
298 	break;
299 
300     case CKK_DES2:
301 	value = "CKK_DES2";
302 	break;
303 
304     case CKK_DES3:
305 	value = "CKK_DES3";
306 	break;
307 
308     case CKK_AES:
309 	value = "CKK_AES";
310 	break;
311 
312     case CKK_MD5_HMAC:
313         value = "CKK_MD5_HMAC";
314 	break;
315 
316     case CKK_SHA_1_HMAC:
317 	value = "CKK_SHA_1_HMAC";
318 	break;
319 
320     case CKK_RIPEMD128_HMAC:
321 	value = "CKK_RIPEMD128_HMAC";
322 	break;
323 
324     case CKK_RIPEMD160_HMAC:
325 	value = "CKK_RIPEMD160_HMAC";
326 	break;
327 
328     case CKK_SHA256_HMAC:
329 	value = "CKK_SHA256_HMAC";
330 	break;
331 
332     case CKK_SHA384_HMAC:
333 	value = "CKK_SHA384_HMAC";
334 	break;
335 
336     case CKK_SHA512_HMAC:
337 	value = "CKK_SHA512_HMAC";
338 	break;
339 
340     case CKK_SHA224_HMAC:
341 	value = "CKK_SHA224_HMAC";
342 	break;
343 
344     case CKK_RSA:
345 	value = "CKK_RSA";
346 	break;
347 
348     case CKK_DSA:
349 	value = "CKK_RSA";
350 	break;
351 
352     case CKK_DH:
353 	value = "CKK_DH";
354 	break;
355 
356     case CKK_EC:
357 	value = "CKK_EC";
358 	break;
359 
360     case CKK_EC_EDWARDS:
361 	value = "CKK_EC_EDWARDS";
362 	break;
363 
364     default:
365 	value = "unsupported";
366     }
367 
368     fprintf(fp, "%*sCKA_KEY_TYPE: %s\n", offset, "", value);
369 
370 }
371 
372 
fprintf_object_class(FILE * fp,char * unused,CK_ATTRIBUTE_PTR attr,bool unused2,int offset)373 static void fprintf_object_class(FILE *fp, char *unused, CK_ATTRIBUTE_PTR attr, bool unused2, int offset)
374 {
375 
376     char *value;
377 
378     switch( *(CK_OBJECT_CLASS *)attr->pValue ) {
379     case CKO_DATA:
380 	value = "CKO_DATA";
381 	break;
382 
383     case CKO_CERTIFICATE:
384 	value = "CKO_CERTIFICATE";
385 	break;
386 
387     case CKO_PUBLIC_KEY:
388 	value = "CKO_PUBLIC_KEY";
389 	break;
390 
391     case CKO_PRIVATE_KEY:
392 	value = "CKO_PRIVATE_KEY";
393 	break;
394 
395     case CKO_SECRET_KEY:
396 	value = "CKO_SECRET_KEY";
397 	break;
398 
399     case CKO_HW_FEATURE:
400 	value = "CKO_HW_FEATURE";
401 	break;
402 
403     case CKO_DOMAIN_PARAMETERS:
404 	value = "CKO_DOMAIN_PARAMETERS";
405 	break;
406 
407     case CKO_MECHANISM:
408 	value = "CKO_MECHANISM";
409 	break;
410 
411     case CKO_OTP_KEY:
412 	value = "CKO_OTP_KEY";
413 	break;
414 
415     default:
416 	value = (*(CK_OBJECT_CLASS *)attr->pValue) & CKO_VENDOR_DEFINED ? "CKO_VENDOR_DEFINED" : "??unknown object type??" ;
417 	break;
418     }
419 
420     fprintf(fp, "%*sCKA_CLASS: %s\n", offset, "", value);
421 }
422 
423 
fprintf_boolean_attr(FILE * fp,char * name,CK_ATTRIBUTE_PTR attr,bool commented,int offset)424 static void fprintf_boolean_attr(FILE *fp, char *name, CK_ATTRIBUTE_PTR attr, bool commented, int offset)
425 {
426     fprintf (fp, "%s%*s%s: %s\n", commented ? "# " : "", offset, "", name, *((CK_BBOOL *)(attr->pValue))== CK_TRUE ? "true" : "false");
427 }
428 
fprintf_hex_attr(FILE * fp,char * name,CK_ATTRIBUTE_PTR attr,bool commented,int offset)429 static void fprintf_hex_attr(FILE *fp, char *name, CK_ATTRIBUTE_PTR attr, bool commented, int offset)
430 {
431     int i;
432 
433     fprintf(fp, "%s%*s%s: 0x", commented ? "# " : "", offset, "", name);
434     for(i=0; i<attr->ulValueLen; i++) {
435 	fprintf(fp, "%02x", ((unsigned char* )(attr->pValue))[i] );
436     }
437 
438     fprintf(fp, "\n");
439 }
440 
441 /* _fprintf_str_attr not meant to be used directly, as there is no check about printability */
442 /* use fprintf_str_attr or fprintf_date_attr instead */
_fprintf_str_attr(FILE * fp,char * name,CK_ATTRIBUTE_PTR attr,bool commented,int offset)443 static void _fprintf_str_attr(FILE *fp, char *name, CK_ATTRIBUTE_PTR attr, bool commented, int offset)
444 {
445     fprintf(fp, "%s%*s%s: \"%.*s\"\n", commented ? "# " : "", offset, "", name, (int)(attr->ulValueLen), (unsigned char* )(attr->pValue));
446 }
447 
448 
449 /* check if we can print it as a string (i.e. no special character) */
450 /* otherwise, print as hex. */
451 
fprintf_str_attr(FILE * fp,char * name,CK_ATTRIBUTE_PTR attr,bool commented,int offset)452 static void fprintf_str_attr(FILE *fp, char *name, CK_ATTRIBUTE_PTR attr, bool commented, int offset)
453 {
454     bool seems_printable = false;
455     int i;
456 
457     /* simple check: verify all can be printed */
458     for(i=0; i<attr->ulValueLen; i++) {
459 	if(!isprint(((unsigned char *)(attr->pValue))[i])) {
460 	    goto not_printable; /* exit loop prematurely */
461 	}
462     }
463     seems_printable = true;
464 
465 not_printable:
466 	/* do nothing, seems_printable worths 0 */
467 
468     seems_printable ? _fprintf_str_attr(fp,name,attr,commented,offset) : fprintf_hex_attr(fp,name,attr,commented,offset);
469 
470 }
471 
472 /* date is a special case. If it looks like a date, print it in plain characters */
473 /* otherwise take no risk and print as hex value */
474 
fprintf_date_attr(FILE * fp,char * name,CK_ATTRIBUTE_PTR attr,bool commented,int offset)475 static void fprintf_date_attr(FILE *fp, char *name, CK_ATTRIBUTE_PTR attr, bool commented, int offset)
476 {
477     bool looks_like_a_date = false;
478 
479     if(attr->ulValueLen==8) {
480 	int i;
481 	/* simple check: verify we have digits everywhere */
482 	/* a more sophisticated one would check if it looks like a REAL date... */
483 	for(i=0; i<8; i++) {
484 	    if(!isdigit(((unsigned char *)(attr->pValue))[i])) {
485 		goto not_a_date; /* exit loop prematurely */
486 	    }
487 	}
488 	looks_like_a_date = true;
489     }
490 
491 not_a_date:
492 	/* do nothing, looks_like_a_date worths false */
493 
494     looks_like_a_date ? _fprintf_str_attr(fp,name,attr,commented,offset) : fprintf_hex_attr(fp,name,attr,commented,offset);
495 }
496 
497 /* fprintf_template_attr() function and support functions */
498 
compare_attr(const void * a,const void * b)499 static int compare_attr( const void *a, const void *b)
500 {
501     return ((CK_ATTRIBUTE_PTR)a)->type == ((CK_ATTRIBUTE_PTR)b)->type ? 0 : -1;
502 }
503 
504 
505 
fprintf_mechanism_type_array(FILE * fp,char * name,CK_ATTRIBUTE_PTR attr,bool commented,int offset)506 static void fprintf_mechanism_type_array(FILE *fp, char *name, CK_ATTRIBUTE_PTR attr, bool commented, int offset)
507 {
508     int i;
509     CK_MECHANISM_TYPE_PTR mech_array = attr->pValue; /* attr_array will be used as the array to walk mechanisms */
510     size_t mech_arrayitems = attr->ulValueLen / sizeof(CK_MECHANISM_TYPE);
511 
512     fprintf(fp, "%s%*s%s: {\n", commented ? "# " : "", offset, "", name);
513 
514     for(i=0; i<mech_arrayitems; i++) {
515 	fprintf(fp, "%s%*s%s\n", commented ? "# " : "", offset+INDENTATION_OFFSET, "", pkcs11_get_mechanism_name_from_type(mech_array[i]));
516     }
517 
518     fprintf(fp, "%s%*s}\n", commented ? "# " : "", offset, "");
519 }
520 
fprintf_template_attr_member(FILE * fp,CK_ATTRIBUTE_PTR attr,int offset)521 static void fprintf_template_attr_member(FILE *fp, CK_ATTRIBUTE_PTR attr, int offset)
522 {
523 
524     /* a collection of possible values found in templates */
525     /* all attributes are uncommented */
526     static const attr_printer attriblist[] = {
527 	{ CKA_ALLOWED_MECHANISMS, fprintf_mechanism_type_array, "CKA_ALLOWED_MECHANISMS", false },
528 	{ CKA_CHECK_VALUE, fprintf_hex_attr, "CKA_CHECK_VALUE", true },
529 	{ CKA_CLASS, fprintf_object_class, "CKA_CLASS", false  },
530 	{ CKA_DECRYPT, fprintf_boolean_attr, "CKA_DECRYPT", false },
531 	{ CKA_DERIVE, fprintf_boolean_attr, "CKA_DERIVE", false },
532 	{ CKA_EC_PARAMS, fprintf_hex_attr, "CKA_EC_PARAMS", true },
533 	{ CKA_ENCRYPT, fprintf_boolean_attr, "CKA_ENCRYPT", false },
534 	{ CKA_END_DATE, fprintf_date_attr, "CKA_END_DATE", false },
535 	{ CKA_EXTRACTABLE, fprintf_boolean_attr, "CKA_EXTRACTABLE", false },
536 	{ CKA_ID, fprintf_str_attr, "CKA_ID", false },
537 	{ CKA_KEY_TYPE, fprintf_key_type, "CKA_KEY_TYPE", false },
538 	{ CKA_LABEL, fprintf_str_attr, "CKA_LABEL", false },
539 	{ CKA_MODIFIABLE, fprintf_boolean_attr, "CKA_MODIFIABLE", false },
540 	{ CKA_PRIVATE, fprintf_boolean_attr, "CKA_PRIVATE", false },
541 	{ CKA_SENSITIVE, fprintf_boolean_attr, "CKA_SENSITIVE", false },
542 	{ CKA_SIGN, fprintf_boolean_attr, "CKA_SIGN", false },
543 	{ CKA_SIGN_RECOVER, fprintf_boolean_attr, "CKA_SIGN_RECOVER", false },
544 	{ CKA_START_DATE, fprintf_date_attr, "CKA_START_DATE", false },
545 	{ CKA_SUBJECT, fprintf_hex_attr, "CKA_SUBJECT", false },
546 	{ CKA_TOKEN, fprintf_boolean_attr, "CKA_TOKEN", false },
547 	{ CKA_UNWRAP, fprintf_boolean_attr, "CKA_UNWRAP", false },
548 	{ CKA_VERIFY, fprintf_boolean_attr, "CKA_VERIFY", false },
549 	{ CKA_VERIFY_RECOVER, fprintf_boolean_attr, "CKA_VERIFY_RECOVER", false },
550 	{ CKA_WRAP, fprintf_boolean_attr, "CKA_WRAP", false },
551     };
552 
553     size_t nelem = sizeof attriblist / sizeof(attr_printer);
554     attr_printer key = { attr->type, NULL, NULL, false };
555     attr_printer *match = lfind(&key, attriblist, &nelem, sizeof(attr_printer), compare_attr);
556 
557     if(match) {
558 	match->func_ptr(fp, match->name, attr, false, offset ); /* we ignore the comment argument */
559     }
560 
561 }
562 
fprintf_template_attr(FILE * fp,char * name,CK_ATTRIBUTE_PTR attr,bool commented,int offset)563 static void fprintf_template_attr(FILE *fp, char *name, CK_ATTRIBUTE_PTR attr, bool commented, int offset)
564 {
565     int i;
566     CK_ATTRIBUTE_PTR attr_array = attr->pValue; /* attr_array will be used as the array to walk template */
567     size_t attr_arrayitems = attr->ulValueLen / sizeof(CK_ATTRIBUTE);
568 
569     fprintf(fp, "%s%*s%s: {\n", commented ? "# " : "", offset, "", name);
570 
571     for(i=0; i<attr_arrayitems; i++) {
572 	fprintf(fp, "%s", commented ? "# " : "");
573 	fprintf_template_attr_member(fp, &attr_array[i], offset+INDENTATION_OFFSET);
574     }
575 
576     fprintf(fp, "%s%*s}\n", commented ? "# " : "", offset, "");
577 }
578 
579 /*------------------------------------------------------------------------*/
580 
581 
sprintf_hex_buffer(CK_BYTE_PTR buffer,CK_ULONG len)582 static char * sprintf_hex_buffer(CK_BYTE_PTR buffer, CK_ULONG len)
583 {
584 
585     char *allocated = malloc(len*2+3);
586 
587     if(allocated==NULL) {
588 	fprintf(stderr, "***Error: memory allocation\n");
589     } else {
590 
591 	int i;
592 
593 	allocated[0]='0';
594 	allocated[1]='x';
595 
596 	for(i=0; i<len; i++) {
597 	    snprintf(&allocated[2+i*2], 3, "%02x", buffer[i] );
598 	}
599     }
600 
601     return allocated;
602 }
603 
604 /* _sprintf_str_buffer not meant to be used directly, as there is no check about printability */
605 /* use sprintf_str_buffer_safe instead */
_sprintf_str_buffer(CK_BYTE_PTR buffer,CK_ULONG len)606 static char * _sprintf_str_buffer(CK_BYTE_PTR buffer, CK_ULONG len)
607 {
608     char *allocated = malloc(len+3);
609 
610     if(allocated==NULL) {
611 	fprintf(stderr, "***Error: memory allocation\n");
612     } else {
613 	snprintf(allocated,len+3, "\"%.*s\"", (int)len, buffer);
614     }
615     return allocated;
616 }
617 
618 
619 /* check if we can print the buffer as a string (i.e. no special character) */
620 /* otherwise, print as hex. */
621 
sprintf_str_buffer_safe(CK_BYTE_PTR buffer,CK_ULONG len)622 static char * sprintf_str_buffer_safe(CK_BYTE_PTR buffer, CK_ULONG len)
623 {
624     int seems_printable = 0;
625     int i;
626 
627     /* simple check: verify all can be printed */
628     for(i=0; i<len; i++) {
629 	if(!isprint(buffer[i])) {
630 	    goto not_printable; /* exit loop prematurely */
631 	}
632     }
633     seems_printable = 1;
634 
635 not_printable:
636 	/* do nothing, seems_printable worths 0 */
637 
638     return seems_printable ? _sprintf_str_buffer(buffer,len) : sprintf_hex_buffer(buffer,len);
639 
640 }
641 
free_sprintf_str_buffer_safe_buf(char * ptr)642 static void free_sprintf_str_buffer_safe_buf(char *ptr)
643 {
644     if(ptr) { free(ptr); }
645 }
646 
647 /*------------------------------------------------------------------------*/
648 
649 
_mgfstring(CK_RSA_PKCS_MGF_TYPE mgf)650 static char * const _mgfstring(CK_RSA_PKCS_MGF_TYPE mgf)
651 {
652     char *retval = NULL;
653 
654     switch(mgf) {
655     case CKG_MGF1_SHA1:
656 	retval =  "CKG_MGF1_SHA1";
657 	break;
658 
659     case CKG_MGF1_SHA256:
660 	retval = "CKG_MGF1_SHA256";
661 	break;
662 
663     case CKG_MGF1_SHA384:
664 	retval = "CKG_MGF1_SHA384";
665 	break;
666 
667     case CKG_MGF1_SHA512:
668 	retval = "CKG_MGF1_SHA512";
669 	break;
670 
671     case CKG_MGF1_SHA224:
672 	retval = "CKG_MGF1_SHA224";
673 	break;
674 
675     }
676 
677     return retval;
678 }
679 
_hashstring(CK_MECHANISM_TYPE hash)680 static char * const _hashstring(CK_MECHANISM_TYPE hash)
681 {
682     char *retval = NULL;
683 
684     switch(hash) {
685     case CKM_MD2:
686 	retval = "CKM_MD2";
687 	break;
688 
689     case CKM_MD5:
690 	retval = "CKM_MD5";
691 	break;
692 
693     case CKM_SHA_1:
694 	retval = "CKM_SHA_1";
695 	break;
696 
697     case CKM_RIPEMD128:
698 	retval = "CKM_RIPEMD128";
699 	break;
700 
701     case CKM_RIPEMD160:
702 	retval = "CKM_RIPEMD160";
703 	break;
704 
705     case CKM_SHA256:
706 	retval = "CKM_SHA256";
707 	break;
708 
709     case CKM_SHA224:
710 	retval = "CKM_SHA224";
711 	break;
712 
713     case CKM_SHA384:
714 	retval = "CKM_SHA384";
715 	break;
716 
717     case CKM_SHA512:
718 	retval = "CKM_SHA512";
719 	break;
720     }
721 
722     return retval;
723 
724 }
725 
_output_wrapped_key_header(wrappedKeyCtx * wctx,FILE * fp)726 static func_rc _output_wrapped_key_header(wrappedKeyCtx *wctx, FILE *fp)
727 {
728 
729     time_t now = time(NULL);
730     char hostname[255];
731 
732     /* keyindex: in case of envelope wrapping, the index shall always be the outer */
733     int keyindex = wctx->is_envelope ? WRAPPEDKEYCTX_INNER_KEY_INDEX : WRAPPEDKEYCTX_LONE_KEY_INDEX;
734 
735     char *wctxlabel = wctx->wrappedkeylabel;
736     char *handlelabel = pkcs11_alloclabelforhandle(wctx->p11Context, wctx->key[keyindex].wrappedkeyhandle);
737     char *wrappedkeylabel = wctxlabel ? wctxlabel : handlelabel ? handlelabel : "-no label found-";
738 
739     gethostname(hostname, 255);
740     hostname[254]=0;		/* just to be sure... */
741 
742     fprintf(fp, \
743 	    "########################################################################\n"
744 	    "#\n"
745 	    "# key <%s> wrapped by key <%s>\n"
746 	    "# wrapped on host <%s>\n"
747 	    "# operation date and time (UTC): %s"
748 	    "# wrapping algorithm: %s\n"
749 	    "#\n"
750 	    "# use p11unwrap from pkcs11-tools to unwrap key on dest. PKCS#11 token\n"
751 	    "#\n"
752 	    "# grammar for this file:\n"
753 	    "# ----------------------\n"
754 	    "#\n"
755 	    "# - lines starting with '#' are ignored\n"
756 	    "#\n"
757 	    "# - [ATTRIBUTE] : [VALUE]\n"
758 	    "#   where [ATTRIBUTE] is any of the following:\n"
759 	    "#     Content-Type ( value is application/pkcs11-tools)\n"
760 	    "#     Wrapping-Algorithm: execute p11wrap -h for syntax\n"
761 	    "#     CKA_LABEL\n"
762 	    "#     CKA_ID\n"
763 	    "#     CKA_CLASS\n"
764 	    "#     CKA_TOKEN\n"
765 	    "#     CKA_KEY_TYPE\n"
766 	    "#     CKA_ENCRYPT\n"
767 	    "#     CKA_DECRYPT\n"
768 	    "#     CKA_WRAP\n"
769 	    "#     CKA_UNWRAP\n"
770 	    "#     CKA_SIGN\n"
771 	    "#     CKA_VERIFY\n"
772 	    "#     CKA_DERIVE\n"
773 	    "#     CKA_PRIVATE\n"
774 	    "#     CKA_SENSITIVE\n"
775 	    "#     CKA_EXTRACTABLE\n"
776 	    "#     CKA_MODIFIABLE\n"
777 	    "#     CKA_START_DATE\n"
778 	    "#     CKA_END_DATE\n"
779 	    "#     CKA_CHECK_VALUE\n"
780 	    "#     CKA_WRAP_TEMPLATE\n"
781 	    "#     CKA_UNWRAP_TEMPLATE\n"
782 	    "#     CKA_ALLOWED_MECHANISMS\n"
783 	    "#   where, depending on the attribute, [VALUE] can be one of the following:\n"
784             "#     \"Hello world\" (printable string)\n"
785 	    "#      0x1A2B3C4D (hex bytes)\n"
786 	    "#      20150630   (date)\n"
787 	    "#      true/false/CK_TRUE/CK_FALSE/yes/no (boolean)\n"
788 	    "#      { attribute=value attribute=value ... }"
789 	    "#      { mechanism mechanism ... }"
790 	    "#\n"
791 	    "# - wrapped key is contained between -----BEGIN WRAPPED KEY-----\n"
792             "#   and -----END WRAPPED KEY----- marks and is Base64 encoded\n"
793 	    "#\n"
794 	    "########################################################################\n"
795 	    "Content-Type: application/pkcs11-tools\n"
796 	    "Grammar-Version: " SUPPORTED_GRAMMAR_VERSION "\n"
797 	    "Wrapping-Key: \"%s\"\n",
798 	    wrappedkeylabel,
799 	    wctx->wrappingkeylabel,
800 	    hostname,
801 	    asctime(gmtime(&now)),
802 	    get_wrapping_algorithm_short(wctx),
803 	    wctx->wrappingkeylabel );
804 
805     free(handlelabel);		/* we must free this structure */
806 
807     if(fprintf_wrapping_algorithm_full(fp, wctx, NULL, 0, WRAPPEDKEYCTX_NO_INDEX) != rc_ok) {
808 	fprintf(stderr, "Error: unsupported wrapping algorithm.\n");
809 	return rc_error_unknown_wrapping_alg;
810     }
811 
812     return rc_ok;
813 }
814 
_output_wrapped_keys_b64(wrappedKeyCtx * wctx,FILE * fp)815 static func_rc _output_wrapped_keys_b64(wrappedKeyCtx *wctx, FILE *fp)
816 {
817     func_rc rc = rc_ok;
818     BIO *bio_stdout = NULL, *bio_b64 = NULL;
819 
820     bio_b64 = BIO_new( BIO_f_base64() );
821     if(bio_b64==NULL) {
822 	P_ERR();
823 	rc = rc_error_openssl_api;
824 	goto err;
825     }
826 
827     bio_stdout = BIO_new( BIO_s_file() );
828     if(bio_stdout==NULL) {
829 	P_ERR();
830 	rc = rc_error_openssl_api;
831 	goto err;
832     }
833 
834     BIO_set_fp(bio_stdout, fp, BIO_NOCLOSE);
835 
836     if(wctx->is_envelope) {
837 	BIO_puts(bio_stdout, "-----BEGIN OUTER WRAPPED KEY-----\n");
838 	BIO_flush(bio_stdout);
839 	BIO_push(bio_b64, bio_stdout);
840 	BIO_write(bio_b64,
841 		  wctx->key[WRAPPEDKEYCTX_OUTER_KEY_INDEX].wrapped_key_buffer,
842 		  wctx->key[WRAPPEDKEYCTX_OUTER_KEY_INDEX].wrapped_key_len);
843 	BIO_flush(bio_b64);
844 	BIO_puts(bio_stdout, "-----END OUTER WRAPPED KEY-----\n");
845 	BIO_flush(bio_stdout);
846     }
847 
848     BIO_puts(bio_stdout, wctx->is_envelope ? "-----BEGIN INNER WRAPPED KEY-----\n" : "-----BEGIN WRAPPED KEY-----\n");
849     BIO_flush(bio_stdout);
850     BIO_push(bio_b64, bio_stdout);
851     BIO_write(bio_b64,
852 	      wctx->key[WRAPPEDKEYCTX_INNER_OR_LONE_KEY_INDEX].wrapped_key_buffer,
853 	      wctx->key[WRAPPEDKEYCTX_INNER_OR_LONE_KEY_INDEX].wrapped_key_len);
854     BIO_flush(bio_b64);
855     BIO_puts(bio_stdout, wctx->is_envelope ? "-----END INNER WRAPPED KEY-----\n" : "-----END WRAPPED KEY-----\n");
856     BIO_flush(bio_stdout);
857 
858  err:
859     if(bio_stdout) BIO_free(bio_stdout);
860     if(bio_b64) BIO_free(bio_b64);
861 
862     return rc;
863 }
864 
865 
_output_wrapped_key_attributes(wrappedKeyCtx * wctx,FILE * fp)866 static func_rc _output_wrapped_key_attributes(wrappedKeyCtx *wctx, FILE *fp)
867 {
868     func_rc rc = rc_ok;
869 
870     pkcs11AttrList *wrappedkey_attrs = NULL;
871     CK_ATTRIBUTE_PTR o_attr = NULL;
872     size_t alist_len=0;
873 
874     static attr_printer seckalist[] = {
875 	{ CKA_LABEL, fprintf_str_attr, "CKA_LABEL", false },
876 	{ CKA_ID, fprintf_str_attr, "CKA_ID", false },
877 	{ CKA_CLASS, fprintf_object_class, "CKA_CLASS", false  },
878 	{ CKA_TOKEN, fprintf_boolean_attr, "CKA_TOKEN", false  },
879 	{ CKA_KEY_TYPE, fprintf_key_type, "CKA_KEY_TYPE", false  },
880 	{ CKA_ALLOWED_MECHANISMS, fprintf_mechanism_type_array, "CKA_ALLOWED_MECHANISMS", false },
881 	{ CKA_ENCRYPT, fprintf_boolean_attr, "CKA_ENCRYPT", false },
882 	{ CKA_DECRYPT, fprintf_boolean_attr, "CKA_DECRYPT", false },
883 	{ CKA_WRAP, fprintf_boolean_attr, "CKA_WRAP", false },
884 	{ CKA_WRAP_TEMPLATE, fprintf_template_attr, "CKA_WRAP_TEMPLATE", false },
885 	{ CKA_UNWRAP, fprintf_boolean_attr, "CKA_UNWRAP", false },
886 	{ CKA_UNWRAP_TEMPLATE, fprintf_template_attr, "CKA_UNWRAP_TEMPLATE", false },
887 	{ CKA_SIGN, fprintf_boolean_attr, "CKA_SIGN", false },
888 	{ CKA_VERIFY, fprintf_boolean_attr, "CKA_VERIFY", false },
889 	{ CKA_DERIVE, fprintf_boolean_attr, "CKA_DERIVE", false },
890 	{ CKA_DERIVE_TEMPLATE, fprintf_template_attr, "CKA_DERIVE_TEMPLATE", false },
891 	{ CKA_PRIVATE, fprintf_boolean_attr, "CKA_PRIVATE", false },
892 	{ CKA_SENSITIVE, fprintf_boolean_attr, "CKA_SENSITIVE", false },
893 	{ CKA_EXTRACTABLE, fprintf_boolean_attr, "CKA_EXTRACTABLE", false },
894 	{ CKA_MODIFIABLE, fprintf_boolean_attr, "CKA_MODIFIABLE", false },
895 	{ CKA_START_DATE, fprintf_date_attr, "CKA_START_DATE", false },
896 	{ CKA_END_DATE, fprintf_date_attr, "CKA_END_DATE", false },
897 	{ CKA_CHECK_VALUE, fprintf_hex_attr, "CKA_CHECK_VALUE", true }, /* Not valid in C_Unwrap() template */
898     };
899 
900     static attr_printer prvkalist[] = {
901 	{ CKA_LABEL, fprintf_str_attr, "CKA_LABEL", false },
902 	{ CKA_ID, fprintf_str_attr, "CKA_ID", false },
903 	{ CKA_CLASS, fprintf_object_class, "CKA_CLASS", false },
904 	{ CKA_TOKEN, fprintf_boolean_attr, "CKA_TOKEN", false },
905 	{ CKA_KEY_TYPE, fprintf_key_type, "CKA_KEY_TYPE", false },
906 	{ CKA_ALLOWED_MECHANISMS, fprintf_mechanism_type_array, "CKA_ALLOWED_MECHANISMS", false },
907 	{ CKA_EC_PARAMS, fprintf_hex_attr, "CKA_EC_PARAMS", true }, /* Not valid in C_Unwrap() template */
908 	{ CKA_SUBJECT, fprintf_hex_attr, "CKA_SUBJECT", false },
909 	{ CKA_DECRYPT, fprintf_boolean_attr, "CKA_DECRYPT", false },
910 	{ CKA_UNWRAP, fprintf_boolean_attr, "CKA_UNWRAP", false },
911 	{ CKA_UNWRAP_TEMPLATE, fprintf_template_attr, "CKA_UNWRAP_TEMPLATE", false },
912 	{ CKA_SIGN, fprintf_boolean_attr, "CKA_SIGN", false },
913 	{ CKA_SIGN_RECOVER, fprintf_boolean_attr, "CKA_SIGN_RECOVER", false },
914 	{ CKA_DERIVE, fprintf_boolean_attr, "CKA_DERIVE", false },
915 	{ CKA_DERIVE_TEMPLATE, fprintf_template_attr, "CKA_DERIVE_TEMPLATE", false },
916 	{ CKA_PRIVATE, fprintf_boolean_attr, "CKA_PRIVATE", false },
917 	{ CKA_SENSITIVE, fprintf_boolean_attr, "CKA_SENSITIVE", false },
918 	{ CKA_EXTRACTABLE, fprintf_boolean_attr, "CKA_EXTRACTABLE", false },
919 	{ CKA_MODIFIABLE, fprintf_boolean_attr, "CKA_MODIFIABLE", false },
920 	{ CKA_START_DATE, fprintf_date_attr, "CKA_START_DATE", false },
921 	{ CKA_END_DATE, fprintf_date_attr, "CKA_END_DATE", false },
922     };
923 
924     attr_printer *alist=NULL;
925 
926     switch(wctx->key[WRAPPEDKEYCTX_INNER_OR_LONE_KEY_INDEX].wrappedkeyobjclass) {
927     case CKO_SECRET_KEY:
928 	alist = seckalist;
929 	alist_len = sizeof(seckalist)/sizeof(attr_printer);
930 	wrappedkey_attrs = pkcs11_new_attrlist(wctx->p11Context,
931 					       _ATTR(CKA_LABEL),
932 					       _ATTR(CKA_ID),
933 					       _ATTR(CKA_CLASS),
934 					       _ATTR(CKA_TOKEN),
935 					       _ATTR(CKA_KEY_TYPE),
936 					       _ATTR(CKA_ALLOWED_MECHANISMS),
937 					       _ATTR(CKA_ENCRYPT),
938 					       _ATTR(CKA_DECRYPT),
939 					       _ATTR(CKA_WRAP),
940 					       _ATTR(CKA_WRAP_TEMPLATE),
941 					       _ATTR(CKA_UNWRAP),
942 					       _ATTR(CKA_UNWRAP_TEMPLATE),
943 					       _ATTR(CKA_SIGN),
944 					       _ATTR(CKA_VERIFY),
945 					       _ATTR(CKA_DERIVE_TEMPLATE),
946 					       _ATTR(CKA_DERIVE),
947 					       _ATTR(CKA_PRIVATE),
948 					       _ATTR(CKA_SENSITIVE),
949 					       _ATTR(CKA_EXTRACTABLE),
950 					       _ATTR(CKA_MODIFIABLE),
951 					       _ATTR(CKA_START_DATE),
952 					       _ATTR(CKA_END_DATE),
953 					       _ATTR(CKA_CHECK_VALUE),
954 					       _ATTR_END );
955 	break;
956 
957     case CKO_PRIVATE_KEY:
958 	alist = prvkalist;
959 	alist_len = sizeof(prvkalist)/sizeof(attr_printer);
960 	wrappedkey_attrs = pkcs11_new_attrlist(wctx->p11Context,
961 					       _ATTR(CKA_LABEL),
962 					       _ATTR(CKA_ID),
963 					       _ATTR(CKA_CLASS),
964 					       _ATTR(CKA_TOKEN),
965 					       _ATTR(CKA_KEY_TYPE),
966 					       _ATTR(CKA_ALLOWED_MECHANISMS),
967 					       _ATTR(CKA_EC_PARAMS),
968 					       _ATTR(CKA_SUBJECT),
969 					       _ATTR(CKA_DECRYPT),
970 					       _ATTR(CKA_UNWRAP),
971 					       _ATTR(CKA_UNWRAP_TEMPLATE),
972 					       _ATTR(CKA_SIGN),
973 					       _ATTR(CKA_SIGN_RECOVER),
974 					       _ATTR(CKA_DERIVE),
975 					       _ATTR(CKA_DERIVE_TEMPLATE),
976 					       _ATTR(CKA_PRIVATE),
977 					       _ATTR(CKA_SENSITIVE),
978 					       _ATTR(CKA_EXTRACTABLE),
979 					       _ATTR(CKA_MODIFIABLE),
980 					       _ATTR(CKA_START_DATE),
981 					       _ATTR(CKA_END_DATE),
982 					       _ATTR_END );
983 	break;
984 
985     default:
986 	fprintf(stderr,"***Error: Oops... invalid object type, bailing out\n");
987 	rc = rc_error_oops;
988 	goto error;
989     }
990 
991 
992     if( pkcs11_read_attr_from_handle (wrappedkey_attrs, wctx->key[WRAPPEDKEYCTX_INNER_OR_LONE_KEY_INDEX].wrappedkeyhandle) == false) {
993 	fprintf(stderr,"Error: could not read attributes from key with label '%s'\n", wctx->wrappedkeylabel);
994 	rc = rc_error_pkcs11_api;
995 	goto error;
996     }
997 
998     {
999 	size_t i;
1000 
1001 	for(i=0;i<alist_len;i++) {
1002 	    o_attr = pkcs11_get_attr_in_attrlist(wrappedkey_attrs, alist[i].attr_type);
1003 
1004 	    if(o_attr == NULL) {
1005 		fprintf(fp, "# %s attribute not found\n", alist[i].name);
1006 	    } else if (o_attr->type == CKA_EXTRACTABLE) {
1007 		/* security feature: unwrapped keys should not have CKA_EXTRACTABLE set to true */
1008 		fprintf(fp, "CKA_EXTRACTABLE: false\n");
1009 	    } else if (o_attr->type == CKA_TOKEN) {
1010 		/* unwrapped keys always have CKA_TOKEN set to true */
1011 		fprintf(fp, "CKA_TOKEN: true\n");
1012 	    } else if (o_attr->ulValueLen == 0) {
1013 		fprintf(fp, "# %s attribute is empty\n", alist[i].name);
1014 	    } else if ( ( o_attr->type==CKA_UNWRAP_TEMPLATE ||
1015 			  o_attr->type==CKA_DERIVE_TEMPLATE ||
1016 			  o_attr->type==CKA_WRAP_TEMPLATE) &&
1017 			o_attr->ulValueLen % sizeof(CK_ATTRIBUTE) != 0 ) {
1018 		/* on Safenet Luna, private keys have, by default, templates that are 1 byte long */
1019 		/* which is not a valid content for templates */
1020 		fprintf(fp, "# %s attribute invalid on the source token\n", alist[i].name);
1021 	    } else {
1022 		alist[i].func_ptr(fp, alist[i].name, o_attr, alist[i].commented, 0 );
1023 	    }
1024 	}
1025     }
1026 
1027 
1028 error:
1029 
1030     pkcs11_delete_attrlist(wrappedkey_attrs);
1031 
1032     return rc;
1033 
1034 }
1035 
_output_public_key_b64(wrappedKeyCtx * wctx,FILE * fp)1036 static func_rc _output_public_key_b64(wrappedKeyCtx *wctx, FILE *fp)
1037 {
1038     func_rc rc = rc_ok;
1039     BIO *bio_stdout = NULL;
1040 
1041     bio_stdout = BIO_new( BIO_s_file() );
1042     if(bio_stdout==NULL) {
1043 	P_ERR();
1044 	rc = rc_error_openssl_api;
1045 	goto err;
1046     }
1047 
1048     BIO_set_fp(bio_stdout, fp, BIO_NOCLOSE);
1049     rc = pkcs11_cat_object_with_handle(wctx->p11Context, wctx->pubkhandle, 0, bio_stdout);
1050 
1051 err:
1052     if(bio_stdout) BIO_free(bio_stdout);
1053 
1054     return rc;
1055 }
1056 
_output_public_key_attributes(wrappedKeyCtx * wctx,FILE * fp)1057 static func_rc _output_public_key_attributes(wrappedKeyCtx *wctx, FILE *fp)
1058 {
1059     func_rc rc = rc_ok;
1060 
1061     pkcs11AttrList *wrappedkey_attrs = NULL;
1062     CK_ATTRIBUTE_PTR o_attr = NULL;
1063     size_t alist_len=0;
1064 
1065     static attr_printer alist[] = {
1066 	{ CKA_LABEL, fprintf_str_attr, "CKA_LABEL", false },
1067 	{ CKA_ID, fprintf_str_attr, "CKA_ID", false },
1068 	{ CKA_CLASS, fprintf_object_class, "CKA_CLASS", false  },
1069 	{ CKA_TOKEN, fprintf_boolean_attr, "CKA_TOKEN", false  },
1070 	{ CKA_KEY_TYPE, fprintf_key_type, "CKA_KEY_TYPE", false  },
1071 	{ CKA_ALLOWED_MECHANISMS, fprintf_mechanism_type_array, "CKA_ALLOWED_MECHANISMS", false },
1072 	{ CKA_EC_PARAMS, fprintf_hex_attr, "CKA_EC_PARAMS", true },
1073 	{ CKA_SUBJECT, fprintf_hex_attr, "CKA_SUBJECT", false },
1074 	{ CKA_ENCRYPT, fprintf_boolean_attr, "CKA_ENCRYPT", false },
1075 	{ CKA_WRAP, fprintf_boolean_attr, "CKA_WRAP", false },
1076 	{ CKA_WRAP_TEMPLATE, fprintf_template_attr, "CKA_WRAP_TEMPLATE", false },
1077 	{ CKA_VERIFY, fprintf_boolean_attr, "CKA_VERIFY", false },
1078 	{ CKA_VERIFY_RECOVER, fprintf_boolean_attr, "CKA_VERIFY_RECOVER", false },
1079 	{ CKA_DERIVE, fprintf_boolean_attr, "CKA_DERIVE", false },
1080 	{ CKA_PRIVATE, fprintf_boolean_attr, "CKA_PRIVATE", false },
1081 	{ CKA_MODIFIABLE, fprintf_boolean_attr, "CKA_MODIFIABLE", false },
1082 	{ CKA_START_DATE, fprintf_date_attr, "CKA_START_DATE", false },
1083 	{ CKA_END_DATE, fprintf_date_attr, "CKA_END_DATE", false },
1084     };
1085 
1086     alist_len = sizeof(alist)/sizeof(attr_printer);
1087     wrappedkey_attrs = pkcs11_new_attrlist(wctx->p11Context,
1088 					   _ATTR(CKA_LABEL),
1089 					   _ATTR(CKA_ID),
1090 					   _ATTR(CKA_CLASS),
1091 					   _ATTR(CKA_TOKEN),
1092 					   _ATTR(CKA_KEY_TYPE),
1093 					   _ATTR(CKA_ALLOWED_MECHANISMS),
1094 					   _ATTR(CKA_EC_PARAMS),
1095 					   _ATTR(CKA_SUBJECT),
1096 					   _ATTR(CKA_ENCRYPT),
1097 					   _ATTR(CKA_WRAP),
1098 					   _ATTR(CKA_WRAP_TEMPLATE),
1099 					   _ATTR(CKA_VERIFY),
1100 					   _ATTR(CKA_VERIFY_RECOVER),
1101 					   _ATTR(CKA_DERIVE),
1102 					   _ATTR(CKA_PRIVATE),
1103 					   _ATTR(CKA_MODIFIABLE),
1104 					   _ATTR(CKA_START_DATE),
1105 					   _ATTR(CKA_END_DATE),
1106 					   _ATTR_END );
1107 
1108     if( pkcs11_read_attr_from_handle (wrappedkey_attrs, wctx->pubkhandle) == false) {
1109 	fprintf(stderr,"Error: could not read attributes from key with label '%s'\n", wctx->wrappedkeylabel);
1110 	rc = rc_error_pkcs11_api;
1111 	goto error;
1112     }
1113 
1114     size_t i;
1115 
1116     for(i=0;i<alist_len;i++) {
1117 	o_attr = pkcs11_get_attr_in_attrlist(wrappedkey_attrs, alist[i].attr_type);
1118 
1119 	if(o_attr == NULL) {
1120 	    fprintf(fp, "# %s attribute not found\n", alist[i].name);
1121 	} else if (o_attr->type == CKA_EXTRACTABLE) {
1122 	    /* security feature: unwrapped keys should not have CKA_EXTRACTABLE set to true */
1123 	    fprintf(fp, "CKA_EXTRACTABLE: false\n");
1124 	} else if (o_attr->type == CKA_TOKEN) {
1125 	    /* unwrapped keys always have CKA_TOKEN set to true */
1126 	    fprintf(fp, "CKA_TOKEN: true\n");
1127 	} else if (o_attr->ulValueLen == 0) {
1128 	    fprintf(fp, "# %s attribute is empty\n", alist[i].name);
1129 	} else {
1130 	    alist[i].func_ptr(fp, alist[i].name, o_attr, alist[i].commented, 0 );
1131 	}
1132     }
1133 
1134 error:
1135     pkcs11_delete_attrlist(wrappedkey_attrs);
1136     return rc;
1137 }
1138 
_wrap_pkcs1_15(wrappedKeyCtx * wctx)1139 static func_rc _wrap_pkcs1_15(wrappedKeyCtx *wctx)
1140 {
1141     func_rc rc = rc_ok;
1142 
1143     CK_OBJECT_HANDLE wrappingkeyhandle=NULL_PTR;
1144     CK_OBJECT_HANDLE wrappedkeyhandle=NULL_PTR;
1145     CK_OBJECT_CLASS wrappedkeyobjclass;
1146     pkcs11AttrList *wrappedkey_attrs = NULL, *wrappingkey_attrs = NULL;
1147     CK_ATTRIBUTE_PTR o_wrappedkey_bytes, o_modulus, o_keytype;
1148     BIGNUM *bn_wrappingkey_bytes = NULL;
1149     BIGNUM *bn_wrappedkey_bytes = NULL;
1150     int bytelen;
1151     unsigned long keysizeinbytes;
1152 
1153     /* keyindex: in case of envelope wrapping, the index shall always be the outer */
1154     int keyindex = wctx->is_envelope ? WRAPPEDKEYCTX_OUTER_KEY_INDEX : WRAPPEDKEYCTX_LONE_KEY_INDEX;
1155 
1156     /* retrieve keys  */
1157 
1158     if(wctx->is_envelope) {
1159 	/* if envelope encryption, keys have been already found by _wrap_envelope() */
1160 	/* and wctx structure has been populated. */
1161 	wrappedkeyhandle = wctx->key[keyindex].wrappedkeyhandle;
1162 	wrappingkeyhandle = wctx->key[keyindex].wrappingkeyhandle;
1163     } else {
1164 	if (!pkcs11_findpublickey(wctx->p11Context, wctx->wrappingkeylabel, &wrappingkeyhandle)) {
1165 	    fprintf(stderr,"Error: could not find a public key with label '%s'\n", wctx->wrappingkeylabel);
1166 	    rc = rc_error_object_not_found;
1167 	    goto error;
1168 	}
1169 
1170 	/* if we called _wrap() with meth_keyhandle, then the wrappedkeylabel is NULL */
1171 	/* and we can directly use the value in wrappedkeyhabndle */
1172 	if(wctx->wrappedkeylabel==NULL) {
1173 	    wrappedkeyhandle = wctx->key[keyindex].wrappedkeyhandle;
1174 	    /* we need to retrieve the object class */
1175 	    wrappedkeyobjclass = pkcs11_get_object_class(wctx->p11Context, wrappedkeyhandle);
1176 
1177 	    if(wrappedkeyobjclass != CKO_SECRET_KEY) {
1178 		fprintf(stderr,"***Error: PKCS#1 1.5 wrapping algorithm can only wrap secret keys, not private keys\n");
1179 		rc = rc_error_wrong_object_class;
1180 		goto error;
1181 	    }
1182 	} else {
1183 	    if(!pkcs11_findsecretkey(wctx->p11Context, wctx->wrappedkeylabel, &wrappedkeyhandle)) {
1184 		fprintf(stderr,"Error: secret key with label '%s' does not exists\n", wctx->wrappedkeylabel);
1185 		rc = rc_error_object_not_found;
1186 		goto error;
1187 	    }
1188 	}
1189     }
1190 
1191     /* retrieve length of wrapping key */
1192     wrappingkey_attrs = pkcs11_new_attrlist(wctx->p11Context,
1193 					    _ATTR(CKA_MODULUS),
1194 					    _ATTR_END );
1195 
1196     if( pkcs11_read_attr_from_handle (wrappingkey_attrs, wrappingkeyhandle) == false) {
1197 	fprintf(stderr,"Error: could not read CKA_MODULUS_BITS attribute from public key with label '%s'\n", wctx->wrappingkeylabel);
1198 	rc = rc_error_pkcs11_api;
1199 	goto error;
1200     }
1201 
1202     o_modulus = pkcs11_get_attr_in_attrlist(wrappingkey_attrs, CKA_MODULUS);
1203 
1204     /* overwrite existing value */
1205     if ( (bn_wrappingkey_bytes = BN_bin2bn(o_modulus->pValue, o_modulus->ulValueLen, NULL)) == NULL ) {
1206 	P_ERR();
1207 	goto error;
1208     }
1209 
1210     /* extract number of bytes */
1211     bytelen = BN_num_bytes(bn_wrappingkey_bytes);
1212 
1213     /* and adjust value */
1214     BN_set_word(bn_wrappingkey_bytes, (unsigned long)bytelen);
1215 
1216     /* retrieve length of wrapped key */
1217     wrappedkey_attrs = pkcs11_new_attrlist(wctx->p11Context,
1218 					    _ATTR(CKA_KEY_TYPE), /* for DES/DES2/DES3 */
1219 					    _ATTR(CKA_VALUE_LEN), /* caution: value in bytes */
1220 					    _ATTR_END );
1221 
1222     if( pkcs11_read_attr_from_handle (wrappedkey_attrs, wrappedkeyhandle) == false) {
1223 	fprintf(stderr,"Error: could not read CKA_VALUE_LEN attribute from secret key with label '%s'\n", wctx->wrappedkeylabel);
1224 	rc = rc_error_pkcs11_api;
1225 	goto error;
1226     }
1227 
1228     o_wrappedkey_bytes = pkcs11_get_attr_in_attrlist(wrappedkey_attrs, CKA_VALUE_LEN);
1229     /* pkcs11_get_attr_in_attrlist returns the attribute, but we need to check */
1230     /* if there is actually a value attached to it */
1231 
1232     if(o_wrappedkey_bytes && o_wrappedkey_bytes->pValue) {
1233 
1234 
1235 	/* BN_bin2bn works only with big endian, so we must alter data */
1236 	/* if architecture is LE */
1237 
1238 	*((CK_ULONG *)o_wrappedkey_bytes->pValue) = pkcs11_ll_bigendian_ul( *((CK_ULONG *)(o_wrappedkey_bytes->pValue))); /* transform if required */
1239 
1240 	if ( (bn_wrappedkey_bytes = BN_bin2bn( o_wrappedkey_bytes->pValue, o_wrappedkey_bytes->ulValueLen, NULL)  ) == NULL ) {
1241 	    P_ERR();
1242 	    goto error;
1243 	}
1244     } else { /* can be the case for CKK_DES, CKK_DES2 and CKK_DES3 family */
1245 	     /* as these keys have no CKA_VALUE_LEN attribute */
1246 
1247 	o_keytype = pkcs11_get_attr_in_attrlist(wrappedkey_attrs, CKA_KEY_TYPE);
1248 
1249 	switch(*(CK_KEY_TYPE *)(o_keytype->pValue)) {
1250 	case CKK_DES:
1251 	    keysizeinbytes=8;
1252 	    break;
1253 
1254 	case CKK_DES2:
1255 	    keysizeinbytes=16;
1256 	    break;
1257 
1258 	case CKK_DES3:
1259 	    keysizeinbytes=24;
1260 	    break;
1261 
1262 	default:
1263 	    fprintf(stderr,"***Error: unsupported key type for wrapping key\n");
1264 	    rc = rc_error_unsupported;
1265 	    goto error;}
1266 
1267 	/* allocate BN */
1268 	if ( (bn_wrappedkey_bytes = BN_new()) == NULL ) {
1269 	    P_ERR();
1270 	    goto error;
1271 	}
1272 
1273 	if ( BN_set_word(bn_wrappedkey_bytes, keysizeinbytes) == 0) {
1274 	    P_ERR();
1275 	    goto error;
1276 	}
1277     }
1278 
1279 
1280     /* now check that len(wrapped_key) < len(wrapping_key) - 11 */
1281     /* !! lengths being expressed in bytes */
1282 
1283     if(! BN_add_word( bn_wrappedkey_bytes, 11L) ) {
1284 	P_ERR();
1285 	goto error;
1286     }
1287 
1288     /* if bn_wrapped_key  + 11 > bn_wrapping_key, then the wrapping key is too short.  */
1289 
1290     if( BN_cmp( bn_wrappedkey_bytes, bn_wrappingkey_bytes) > 0 ) {
1291 	fprintf(stderr, "Error: wrapping key '%s' is too short to wrap key '%s'\n", wctx->wrappingkeylabel, wctx->wrappedkeylabel);
1292 	rc = rc_error_wrapping_key_too_short;
1293 	goto error;
1294     }
1295 
1296 
1297     /* we are good, let's allocate the memory and wrap */
1298     /* trick: we use now the CKA_MODULUS attribute to size the target buffer */
1299 
1300     wctx->key[keyindex].wrapped_key_buffer = calloc ( o_modulus->ulValueLen, sizeof(unsigned char) );
1301 
1302     if(wctx->key[keyindex].wrapped_key_buffer == NULL) {
1303 	fprintf(stderr,"Error: memory\n");
1304 	rc = rc_error_memory;
1305 	goto error;
1306     }
1307 
1308     wctx->key[keyindex].wrapped_key_len = o_modulus->ulValueLen;
1309 
1310     /* now wrap */
1311 
1312     {
1313 	CK_RV rv;
1314 	CK_MECHANISM mechanism = { CKM_RSA_PKCS, NULL_PTR, 0 };/* PKCS #1 1.5 wrap */
1315 
1316 	rv = wctx->p11Context->FunctionList.C_WrapKey ( wctx->p11Context->Session,
1317 							&mechanism,
1318 							wrappingkeyhandle,
1319 							wrappedkeyhandle,
1320 							wctx->key[keyindex].wrapped_key_buffer,
1321 							&(wctx->key[keyindex].wrapped_key_len) );
1322 
1323 	if(rv!=CKR_OK) {
1324 	    pkcs11_error(rv, "C_WrapKey");
1325 	    rc = rc_error_pkcs11_api;
1326 	    goto error;
1327 	}
1328 	wctx->key[keyindex].wrappedkeyhandle = wrappedkeyhandle;
1329 	wctx->key[keyindex].wrappedkeyobjclass = CKO_SECRET_KEY;
1330 
1331     }
1332 
1333 error:
1334     if(bn_wrappingkey_bytes != NULL) { BN_free(bn_wrappingkey_bytes); bn_wrappingkey_bytes=NULL; }
1335     if(bn_wrappedkey_bytes != NULL) { BN_free(bn_wrappedkey_bytes); bn_wrappedkey_bytes=NULL; }
1336     pkcs11_delete_attrlist(wrappingkey_attrs);
1337     pkcs11_delete_attrlist(wrappedkey_attrs);
1338 
1339     return rc;
1340 }
1341 
1342 
1343 
_wrap_cbcpad(wrappedKeyCtx * wctx)1344 static func_rc _wrap_cbcpad(wrappedKeyCtx *wctx)
1345 {
1346     func_rc rc = rc_ok;
1347 
1348     CK_OBJECT_HANDLE wrappingkeyhandle=NULL_PTR;
1349     CK_OBJECT_HANDLE wrappedkeyhandle=NULL_PTR;
1350     key_type_t keytype;
1351     CK_OBJECT_CLASS wrappedkeyobjclass;
1352     int blocklength;
1353 
1354     /* keyindex: in case of envelope wrapping, the index shall always be the outer */
1355     int keyindex = wctx->is_envelope ? WRAPPEDKEYCTX_INNER_KEY_INDEX : WRAPPEDKEYCTX_LONE_KEY_INDEX;
1356 
1357     /* retrieve keys  */
1358 
1359     /* wrapping key is a secret key */
1360 
1361     if(wctx->is_envelope) {
1362 	/* if envelope encryption, keys have been already found by _wrap_envelope() */
1363 	/* and wctx structure has been populated. */
1364 	wrappedkeyhandle = wctx->key[keyindex].wrappedkeyhandle;
1365 	wrappedkeyobjclass = wctx->key[keyindex].wrappedkeyobjclass;
1366 	wrappingkeyhandle = wctx->key[keyindex].wrappingkeyhandle;
1367     } else {
1368 	if (!pkcs11_findsecretkey(wctx->p11Context, wctx->wrappingkeylabel, &wrappingkeyhandle)) {
1369 	    fprintf(stderr, "***Error: could not find a secret key with label '%s'\n", wctx->wrappingkeylabel);
1370 	    rc = rc_error_object_not_found;
1371 	    goto error;
1372 	}
1373 
1374 	/* if we called _wrap() with meth_keyhandle, then the wrappedkeylabel is NULL */
1375 	/* and we can directly use the value in wrappedkeyhabndle */
1376 	/* however we are still lacking the object class, so we retrieve it from the handle */
1377 	if(wctx->wrappedkeylabel==NULL) {
1378 	    wrappedkeyhandle = wctx->key[keyindex].wrappedkeyhandle;
1379 	    wrappedkeyobjclass = pkcs11_get_object_class(wctx->p11Context, wrappedkeyhandle);
1380 
1381 	    if(wrappedkeyobjclass != CKO_SECRET_KEY && wrappedkeyobjclass != CKO_PRIVATE_KEY) {
1382 		rc = rc_error_oops;
1383 		goto error;
1384 	    }
1385 	} else {
1386 	    /* we have a label, just retrieve handle and object class from label */
1387 	    if(!pkcs11_findprivateorsecretkey(wctx->p11Context, wctx->wrappedkeylabel, &wrappedkeyhandle, &wrappedkeyobjclass)) {
1388 		fprintf(stderr, "***Error: key with label '%s' does not exists\n", wctx->wrappedkeylabel);
1389 		rc = rc_error_object_not_found;
1390 		goto error;
1391 	    }
1392 	}
1393     }
1394 
1395     /* in case of private key, see if we have a match for a public key as well (valid only for token keys) */
1396     if(wrappedkeyobjclass==CKO_PRIVATE_KEY && wctx->wrappedkeylabel) {
1397 	if(!pkcs11_findpublickey(wctx->p11Context, wctx->wrappedkeylabel, &wctx->pubkhandle)) {
1398 	    fprintf(stderr, "***Warning: private key with label '%s' found, but there is no associated public key found with the same label\n", wctx->wrappedkeylabel);
1399 	}
1400     }
1401 
1402     /* determining block size of the block cipher. */
1403     /* retrieve length of wrapping key */
1404     keytype = pkcs11_get_key_type(wctx->p11Context, wrappingkeyhandle);
1405 
1406     switch(keytype) {
1407     case aes:
1408 	blocklength=16;
1409 	break;
1410 
1411     case des:
1412     case des2:
1413     case des3:
1414 	blocklength=8;
1415 	break;
1416 
1417     default:
1418 	fprintf(stderr,"***Error: unsupported key type for wrapping key\n");
1419 	rc = rc_error_unsupported;
1420 	goto error;
1421     }
1422 
1423     /* check length of iv */
1424 
1425     if(wctx->aes_params.iv_len==0) {
1426         /* special case: no IV was given - We do one of our own */
1427 	wctx->aes_params.iv=malloc(blocklength);
1428 	if(wctx->aes_params.iv==NULL) {
1429 	    fprintf(stderr,"***Error: memory allocation\n");
1430 	    rc = rc_error_memory;
1431 	    goto error;
1432 	}
1433 	wctx->aes_params.iv_len = blocklength;
1434 
1435 	/* randomize it */
1436 	pkcs11_getrandombytes(wctx->p11Context, wctx->aes_params.iv,blocklength);
1437 
1438     } else {
1439 	if(wctx->aes_params.iv_len != blocklength) {
1440 	    fprintf(stderr, "***Error: IV vector length(%d) mismatch - %d bytes are required\n", (int)(wctx->aes_params.iv_len), (int)blocklength);
1441 	    rc = rc_error_invalid_parameter_for_method;
1442 	    goto error;
1443 	}
1444     }
1445 
1446 /* now wrap */
1447 
1448     {
1449 	CK_RV rv;
1450 	CK_MECHANISM mechanism = { 0L, wctx->aes_params.iv, wctx->aes_params.iv_len };
1451 	CK_ULONG wrappedkeybuffersize;
1452 
1453 	switch(keytype) {
1454 	case aes:
1455 	    mechanism.mechanism = CKM_AES_CBC_PAD;
1456 	    break;
1457 
1458 	case des:
1459 	    mechanism.mechanism = CKM_DES_CBC_PAD;
1460 	    break;
1461 
1462 	case des2:		/* DES2 and DES3 both use the same mechanism */
1463 	case des3:
1464 	    mechanism.mechanism = CKM_DES3_CBC_PAD;
1465 	    break;
1466 
1467 	default:
1468 	    fprintf(stderr,"***Error: unsupported key type for wrapping key\n");
1469 	    rc = rc_error_unsupported;
1470 	    goto error;
1471 	}
1472 
1473 	/* first call to know what will be the size output buffer */
1474 	rv = wctx->p11Context->FunctionList.C_WrapKey ( wctx->p11Context->Session,
1475 							&mechanism,
1476 							wrappingkeyhandle,
1477 							wrappedkeyhandle,
1478 							NULL,
1479 							&wrappedkeybuffersize );
1480 
1481 	if(rv!=CKR_OK) {
1482 	    pkcs11_error(rv, "C_WrapKey");
1483 	    rc = rc_error_pkcs11_api;
1484 	    goto error;
1485 	}
1486 
1487 	wctx->key[keyindex].wrapped_key_buffer = malloc( wrappedkeybuffersize );
1488 	if(wctx->key[keyindex].wrapped_key_buffer==NULL) {
1489 	    fprintf(stderr,"***Error: memory allocation\n");
1490 	    rc = rc_error_memory;
1491 	    goto error;
1492 	}
1493 	wctx->key[keyindex].wrapped_key_len = wrappedkeybuffersize;
1494 
1495 	/* now we can do the real call, with the real buffer */
1496 	rv = wctx->p11Context->FunctionList.C_WrapKey ( wctx->p11Context->Session,
1497 							&mechanism,
1498 							wrappingkeyhandle,
1499 							wrappedkeyhandle,
1500 							wctx->key[keyindex].wrapped_key_buffer,
1501 							&(wctx->key[keyindex].wrapped_key_len) );
1502 
1503 
1504 	if(rv!=CKR_OK) {
1505 	    pkcs11_error(rv, "C_WrapKey");
1506 	    rc = rc_error_pkcs11_api;
1507 	    goto error;
1508 	}
1509 
1510 	wctx->key[keyindex].wrappedkeyobjclass = wrappedkeyobjclass;
1511 	wctx->key[keyindex].wrappedkeyhandle = wrappedkeyhandle;
1512     }
1513 
1514 error:
1515 
1516     return rc;
1517 }
1518 
1519 
1520 
1521 /*------------------------------------------------------------------------*/
1522 /* wrap a key using CKM_AES_KEY_WRAP or equivalent mechanism              */
1523 /*------------------------------------------------------------------------*/
1524 
_wrap_aes_key_wrap_mech(wrappedKeyCtx * wctx,CK_MECHANISM_TYPE mech[],CK_ULONG mech_size)1525 static func_rc _wrap_aes_key_wrap_mech(wrappedKeyCtx *wctx, CK_MECHANISM_TYPE mech[], CK_ULONG mech_size)
1526 {
1527     func_rc rc = rc_ok;
1528 
1529     CK_OBJECT_HANDLE wrappingkeyhandle=0;
1530     CK_OBJECT_HANDLE wrappedkeyhandle=0;
1531     CK_OBJECT_CLASS wrappedkeyobjclass;
1532     key_type_t keytype;
1533 
1534     /* keyindex: in case of envelope wrapping, the index shall always be the outer */
1535     int keyindex = wctx->is_envelope ? WRAPPEDKEYCTX_INNER_KEY_INDEX : WRAPPEDKEYCTX_LONE_KEY_INDEX;
1536 
1537     /* sanity check */
1538     if(wctx==NULL) {
1539 	fprintf(stderr, "***Error: invalid argument to _wrap_aes_key_wrap_mech()\n");
1540 	rc =rc_error_invalid_parameter_for_method;
1541 	goto error;
1542     }
1543 
1544     if(mech_size==0 || mech_size>AES_WRAP_MECH_SIZE_MAX) {
1545 	fprintf(stderr, "***Error: invalid wrapping mechanism table size\n");
1546 	rc = rc_error_invalid_parameter_for_method;
1547 	goto error;
1548     }
1549 
1550     /* retrieve keys  */
1551 
1552     /* wrapping key is a secret key */
1553 
1554     if(wctx->is_envelope) {
1555 	/* if envelope encryption, keys have been already found by _wrap_envelope() */
1556 	/* and wctx structure has been populated. */
1557 	wrappedkeyhandle = wctx->key[keyindex].wrappedkeyhandle;
1558 	wrappedkeyobjclass = wctx->key[keyindex].wrappedkeyobjclass;
1559 	wrappingkeyhandle = wctx->key[keyindex].wrappingkeyhandle;
1560     } else {
1561 	if (!pkcs11_findsecretkey(wctx->p11Context, wctx->wrappingkeylabel, &wrappingkeyhandle)) {
1562 	    fprintf(stderr,"***Error: could not find a secret key with label '%s'\n", wctx->wrappingkeylabel);
1563 	    rc = rc_error_object_not_found;
1564 	    goto error;
1565 	}
1566 
1567 	/* if we called _wrap() with meth_keyhandle, then the wrappedkeylabel is NULL */
1568 	/* and we can directly use the value in wrappedkeyhabndle */
1569 	/* however we are still lacking the object class, so we retrieve it from the handle */
1570 	if(wctx->wrappedkeylabel==NULL) {
1571 	    wrappedkeyhandle = wctx->key[keyindex].wrappedkeyhandle;
1572 	    wrappedkeyobjclass = pkcs11_get_object_class(wctx->p11Context, wrappedkeyhandle);
1573 
1574 	    if(wrappedkeyobjclass != CKO_SECRET_KEY && wrappedkeyobjclass != CKO_PRIVATE_KEY) {
1575 		rc = rc_error_oops;
1576 		goto error;
1577 	    }
1578 	} else {
1579 	    /* we have a label, just retrieve handle and object class from label */
1580 	    if(!pkcs11_findprivateorsecretkey(wctx->p11Context, wctx->wrappedkeylabel, &wrappedkeyhandle, &wrappedkeyobjclass)) {
1581 		fprintf(stderr, "***Error: key with label '%s' does not exists\n", wctx->wrappedkeylabel);
1582 		rc = rc_error_object_not_found;
1583 		goto error;
1584 	    }
1585 	}
1586     }
1587 
1588     /* in case of private key, see if we have a match for a public key as well (valid only for token keys) */
1589     if(wrappedkeyobjclass==CKO_PRIVATE_KEY && wctx->wrappedkeylabel) {
1590 	if(!pkcs11_findpublickey(wctx->p11Context, wctx->wrappedkeylabel, &wctx->pubkhandle)) {
1591 	    fprintf(stderr, "***Warning: private key with label '%s' found, but there is no associated public key found with the same label\n", wctx->wrappedkeylabel);
1592 	}
1593     }
1594 
1595     /* determining block size of the block cipher. */
1596     /* retrieve length of wrapping key */
1597     keytype = pkcs11_get_key_type(wctx->p11Context, wrappingkeyhandle);
1598 
1599     if(keytype != aes ) {
1600 	fprintf(stderr, "Error: secret key with label '%s' is not an AES key\n", wctx->wrappingkeylabel);
1601 	rc = rc_error_wrong_key_type;
1602 	goto error;
1603 
1604     }
1605 
1606 /* now wrap */
1607 
1608     {
1609 	CK_RV rv;
1610 	CK_MECHANISM mechanism = { 0L, wctx->aes_params.iv, wctx->aes_params.iv_len };
1611 	CK_ULONG wrappedkeybuffersize;
1612 	CK_ULONG i;
1613 
1614 	/* first call to know what will be the size output buffer */
1615 	for(i=0;i< mech_size; i++) {
1616             /* let's try mechanisms one by one, unless the mechanism is already supplied  */
1617 	    /* i.e. if wctx->aes_wrapping_mech != 0 */
1618 	    mechanism.mechanism = wctx->aes_params.aes_wrapping_mech != 0 ? wctx->aes_params.aes_wrapping_mech : mech[i];
1619 	    rv = wctx->p11Context->FunctionList.C_WrapKey ( wctx->p11Context->Session,
1620 							    &mechanism,
1621 							    wrappingkeyhandle,
1622 							    wrappedkeyhandle,
1623 							    NULL,
1624 							    &wrappedkeybuffersize );
1625 	    if(rv!=CKR_OK) {
1626 		pkcs11_error(rv, "C_WrapKey");
1627 		fprintf(stderr, "***Warning: It didn't work with %s\n", pkcs11_get_mechanism_name_from_type(mechanism.mechanism));
1628 	    } else {
1629 		/* it worked, let's remember in wctx the actual mechanism used */
1630 		/* unless it was already supplied */
1631 		if(wctx->aes_params.aes_wrapping_mech==0) {
1632 		    wctx->aes_params.aes_wrapping_mech = mech[i];
1633 		}
1634 		/* and escape loop */
1635 		break;
1636 	    }
1637 
1638 	    if(wctx->aes_params.aes_wrapping_mech != 0) {
1639 		/* special case: if the wrapping mechanism was set by the parser */
1640 		/* through option field, we will not try other mechanisms than the one  */
1641 		/* specified. */
1642 		break;
1643 	    }
1644 	}
1645 
1646 	if(rv!=CKR_OK) {	/* we couldn't find a suitable mech */
1647 	    fprintf(stderr, "***Error: tried all mechanisms, no one worked\n");
1648 	    rc = rc_error_pkcs11_api;
1649 	    goto error;
1650 	}
1651 
1652 	wctx->key[keyindex].wrapped_key_buffer = malloc( wrappedkeybuffersize );
1653 	if(wctx->key[keyindex].wrapped_key_buffer==NULL) {
1654 	    fprintf(stderr,"***Error: memory allocation\n");
1655 	    rc = rc_error_memory;
1656 	    goto error;
1657 	}
1658 	wctx->key[keyindex].wrapped_key_len = wrappedkeybuffersize;
1659 
1660 	/* now we can do the real call, with the real buffer */
1661 	rv = wctx->p11Context->FunctionList.C_WrapKey ( wctx->p11Context->Session,
1662 							&mechanism,
1663 							wrappingkeyhandle,
1664 							wrappedkeyhandle,
1665 							wctx->key[keyindex].wrapped_key_buffer,
1666 							&(wctx->key[keyindex].wrapped_key_len) );
1667 
1668 
1669 	if(rv!=CKR_OK) {
1670 	    pkcs11_error(rv, "C_WrapKey");
1671 	    rc = rc_error_pkcs11_api;
1672 	    goto error;
1673 	}
1674 
1675 	wctx->key[keyindex].wrappedkeyobjclass = wrappedkeyobjclass;
1676 	wctx->key[keyindex].wrappedkeyhandle = wrappedkeyhandle;
1677     }
1678 
1679 error:
1680     return rc;
1681 }
1682 
1683 
1684 /*------------------------------------------------------------------------*/
_wrap_pkcs1_oaep(wrappedKeyCtx * wctx)1685 static func_rc _wrap_pkcs1_oaep(wrappedKeyCtx *wctx)
1686 {
1687     func_rc rc = rc_ok;
1688 
1689     CK_OBJECT_HANDLE wrappingkeyhandle=NULL_PTR;
1690     CK_OBJECT_HANDLE wrappedkeyhandle=NULL_PTR;
1691     CK_OBJECT_CLASS wrappedkeyobjclass;
1692     pkcs11AttrList *wrappedkey_attrs = NULL, *wrappingkey_attrs = NULL;
1693     CK_ATTRIBUTE_PTR o_wrappedkey_bytes, o_modulus, o_keytype;
1694     BIGNUM *bn_wrappingkey_bytes = NULL;
1695     BIGNUM *bn_wrappedkey_bytes = NULL;
1696     int bytelen;
1697     int sizeoverhead;
1698     unsigned long keysizeinbytes;
1699 
1700     /* keyindex: in case of envelope wrapping, the index shall always be the outer */
1701     int keyindex = wctx->is_envelope ? WRAPPEDKEYCTX_OUTER_KEY_INDEX : WRAPPEDKEYCTX_LONE_KEY_INDEX;
1702 
1703     /* retrieve keys  */
1704 
1705     if(wctx->is_envelope) {
1706 	/* if envelope encryption, keys have been already found by _wrap_envelope() */
1707 	/* and wctx structure has been populated. */
1708 	wrappedkeyhandle = wctx->key[keyindex].wrappedkeyhandle;
1709 	wrappingkeyhandle = wctx->key[keyindex].wrappingkeyhandle;
1710     } else {
1711 	if (!pkcs11_findpublickey(wctx->p11Context, wctx->wrappingkeylabel, &wrappingkeyhandle)) {
1712 	    fprintf(stderr,"Error: could not find a public key with label '%s'\n", wctx->wrappingkeylabel);
1713 	    rc = rc_error_object_not_found;
1714 	    goto error;
1715 	}
1716 
1717 	/* if we called _wrap() with meth_keyhandle, then the wrappedkeylabel is NULL */
1718 	/* and we can directly use the value in wrappedkeyhabndle */
1719 	if(wctx->wrappedkeylabel==NULL) {
1720 	    wrappedkeyhandle = wctx->key[keyindex].wrappedkeyhandle;
1721 	    /* we need to retrieve the object class */
1722 	    wrappedkeyobjclass = pkcs11_get_object_class(wctx->p11Context, wrappedkeyhandle);
1723 
1724 	    if(wrappedkeyobjclass != CKO_SECRET_KEY) {
1725 		fprintf(stderr,"***Error: PKCS#1 OAEP wrapping algorithm can only wrap secret keys, not private keys\n");
1726 		rc = rc_error_wrong_object_class;
1727 		goto error;
1728 	    }
1729 	} else {
1730 	    if(!pkcs11_findsecretkey(wctx->p11Context, wctx->wrappedkeylabel, &wrappedkeyhandle)) {
1731 		fprintf(stderr,"Error: secret key with label '%s' does not exists\n", wctx->wrappedkeylabel);
1732 		rc = rc_error_object_not_found;
1733 		goto error;
1734 	    }
1735 	}
1736     }
1737 
1738     /* retrieve length of wrapping key */
1739     wrappingkey_attrs = pkcs11_new_attrlist(wctx->p11Context,
1740 					    _ATTR(CKA_MODULUS),
1741 					    _ATTR_END );
1742 
1743     if( pkcs11_read_attr_from_handle (wrappingkey_attrs, wrappingkeyhandle) == false) {
1744 	fprintf(stderr,"Error: could not read CKA_MODULUS_BITS attribute from public key with label '%s'\n", wctx->wrappingkeylabel);
1745 	rc = rc_error_pkcs11_api;
1746 	goto error;
1747     }
1748 
1749     o_modulus = pkcs11_get_attr_in_attrlist(wrappingkey_attrs, CKA_MODULUS);
1750 
1751     /* overwrite existing value */
1752     if ( (bn_wrappingkey_bytes = BN_bin2bn(o_modulus->pValue, o_modulus->ulValueLen, NULL)) == NULL ) {
1753 	P_ERR();
1754 	goto error;
1755     }
1756 
1757     /* extract number of bytes */
1758     bytelen = BN_num_bytes(bn_wrappingkey_bytes);
1759 
1760     /* and adjust value */
1761     BN_set_word(bn_wrappingkey_bytes, (unsigned long)bytelen);
1762 
1763     /* retrieve length of wrapped key */
1764     wrappedkey_attrs = pkcs11_new_attrlist(wctx->p11Context,
1765 					   _ATTR(CKA_KEY_TYPE), /* needed as CKA_VALUE_LEN might not always be present */
1766 					   _ATTR(CKA_VALUE_LEN), /* caution: value in bytes */
1767 					   _ATTR_END );
1768 
1769     if( pkcs11_read_attr_from_handle (wrappedkey_attrs, wrappedkeyhandle) == false) {
1770 	fprintf(stderr,"Error: could not read attributes from secret key with label '%s'\n", wctx->wrappedkeylabel);
1771 	rc = rc_error_pkcs11_api;
1772 	goto error;
1773     }
1774 
1775     o_wrappedkey_bytes = pkcs11_get_attr_in_attrlist(wrappedkey_attrs, CKA_VALUE_LEN);
1776     /* pkcs11_get_attr_in_attrlist returns the attribute, but we need to check */
1777     /* if there is actually a value attached to it */
1778 
1779     if(o_wrappedkey_bytes && o_wrappedkey_bytes->pValue) {
1780 
1781 
1782 	/* BN_bin2bn works only with big endian, so we must alter data */
1783 	/* if architecture is LE */
1784 
1785 	*((CK_ULONG *)o_wrappedkey_bytes->pValue) = pkcs11_ll_bigendian_ul( *((CK_ULONG *)(o_wrappedkey_bytes->pValue))); /* transform if required */
1786 
1787 	if ( (bn_wrappedkey_bytes = BN_bin2bn( o_wrappedkey_bytes->pValue, o_wrappedkey_bytes->ulValueLen, NULL)  ) == NULL ) {
1788 	    P_ERR();
1789 	    goto error;
1790 	}
1791     } else { /* can be the case for CKK_DES, CKK_DES2 and CKK_DES3 family */
1792 	     /* as these keys have no CKA_VALUE_LEN attribute */
1793 
1794 	o_keytype = pkcs11_get_attr_in_attrlist(wrappedkey_attrs, CKA_KEY_TYPE);
1795 
1796 	switch(*(CK_KEY_TYPE *)(o_keytype->pValue)) {
1797 	case CKK_DES:
1798 	    keysizeinbytes=8;
1799 	    break;
1800 
1801 	case CKK_DES2:
1802 	    keysizeinbytes=16;
1803 	    break;
1804 
1805 	case CKK_DES3:
1806 	    keysizeinbytes=24;
1807 	    break;
1808 
1809 	default:
1810 	    fprintf(stderr,"***Error: unsupported key type for wrapping key\n");
1811 	    rc = rc_error_unsupported;
1812 	    goto error;}
1813 
1814 	/* allocate BN */
1815 	if ( (bn_wrappedkey_bytes = BN_new()) == NULL ) {
1816 	    P_ERR();
1817 	    goto error;
1818 	}
1819 
1820 	if ( BN_set_word(bn_wrappedkey_bytes, keysizeinbytes) == 0) {
1821 	    P_ERR();
1822 	    goto error;
1823 	}
1824     }
1825 
1826     /* now check that len(wrapped_key) < len(wrapping_key) - 2 - 2 * hlen */
1827     /* !! lengths being expressed in bytes */
1828     /* in this version, Hash Algorithm set to SHA-1 and hardcoded */
1829 
1830     /* when SHA1, hlen=20, 2 * hlen + 2 = 42 */
1831     /* when SHA256, hlen=32,  2 * hlen + 2 = 66 */
1832     /* when SHA384, hlen=48,  2 * hlen + 2 = 98 */
1833     /* when SHA512, hlen=64,  2 * hlen + 2 = 130 */
1834 
1835     switch(wctx->oaep_params->hashAlg) {
1836     case CKM_SHA_1:
1837 	sizeoverhead=42;
1838 	break;
1839 
1840     case CKM_SHA256:
1841 	sizeoverhead=66;
1842 	break;
1843 
1844     case CKM_SHA384:
1845 	sizeoverhead=98;
1846 	break;
1847 
1848     case CKM_SHA512:
1849 	sizeoverhead=130;
1850 	break;
1851 
1852     default:
1853 	fprintf(stderr,"***Error: unsupported hashing algorithm for OAEP wrapping\n");
1854 	rc = rc_error_unsupported;
1855 	goto error;
1856     }
1857 
1858 
1859     if(! BN_add_word( bn_wrappedkey_bytes, sizeoverhead) ) {
1860 	P_ERR();
1861 	goto error;
1862     }
1863 
1864     /* if bn_wrapped_key  + sizeoverhead > bn_wrapping_key, then the wrapping key is too short.  */
1865 
1866     if( BN_cmp( bn_wrappedkey_bytes, bn_wrappingkey_bytes) > 0 ) {
1867 	fprintf(stderr, "Error: wrapping key '%s' is too short to wrap key '%s'\n", wctx->wrappingkeylabel, wctx->wrappedkeylabel);
1868 	rc = rc_error_wrapping_key_too_short;
1869 	goto error;
1870     }
1871 
1872 
1873     /* we are good, let's allocate the memory and wrap */
1874     /* trick: we use now the CKA_MODULUS attribute to size the target buffer */
1875 
1876     wctx->key[keyindex].wrapped_key_buffer = calloc ( o_modulus->ulValueLen, sizeof(unsigned char) );
1877 
1878     if(wctx->key[keyindex].wrapped_key_buffer == NULL) {
1879 	fprintf(stderr,"Error: memory\n");
1880 	rc = rc_error_memory;
1881 	goto error;
1882     }
1883 
1884     wctx->key[keyindex].wrapped_key_len = o_modulus->ulValueLen;
1885 
1886     /* now wrap */
1887 
1888     {
1889 	CK_RV rv;
1890 	CK_MECHANISM mechanism = { CKM_RSA_PKCS_OAEP, wctx->oaep_params, sizeof(CK_RSA_PKCS_OAEP_PARAMS) };/* PKCS #1 OAEP wrap */
1891 
1892 	rv = wctx->p11Context->FunctionList.C_WrapKey ( wctx->p11Context->Session,
1893 							&mechanism,
1894 							wrappingkeyhandle,
1895 							wrappedkeyhandle,
1896 							wctx->key[keyindex].wrapped_key_buffer,
1897 							&(wctx->key[keyindex].wrapped_key_len) );
1898 
1899 	if(rv!=CKR_OK) {
1900 	    pkcs11_error(rv, "C_WrapKey");
1901 	    rc = rc_error_pkcs11_api;
1902 	    goto error;
1903 	}
1904 
1905 	wctx->key[keyindex].wrappedkeyhandle = wrappedkeyhandle; /* keep a copy, for the output */
1906 	wctx->key[keyindex].wrappedkeyobjclass = CKO_SECRET_KEY; /* same story */
1907     }
1908 
1909 error:
1910     if(bn_wrappingkey_bytes != NULL) { BN_free(bn_wrappingkey_bytes); bn_wrappingkey_bytes=NULL; }
1911     if(bn_wrappedkey_bytes != NULL) { BN_free(bn_wrappedkey_bytes); bn_wrappedkey_bytes=NULL; }
1912     pkcs11_delete_attrlist(wrappingkey_attrs);
1913     pkcs11_delete_attrlist(wrappedkey_attrs);
1914 
1915     return rc;
1916 }
1917 
1918 
1919 /*------------------------------------------------------------------------*/
_wrap_envelope(wrappedKeyCtx * wctx)1920 static func_rc _wrap_envelope(wrappedKeyCtx *wctx)
1921 {
1922     func_rc rc = rc_ok;
1923     CK_OBJECT_HANDLE wrappingkeyhandle=NULL_PTR;
1924     CK_OBJECT_HANDLE wrappedkeyhandle=NULL_PTR;
1925     CK_OBJECT_CLASS wrappedkeyobjclass;
1926     CK_OBJECT_HANDLE tempaes_handle=0;
1927     CK_BBOOL ck_true = CK_TRUE;
1928 
1929     CK_ATTRIBUTE tempaes_attrs[] = {
1930 	{ CKA_WRAP, &ck_true, sizeof(ck_true) },
1931 	{ CKA_EXTRACTABLE, &ck_true, sizeof(ck_true) }
1932     };
1933 
1934     char tempaes_label[32];
1935 
1936     if (!pkcs11_findpublickey(wctx->p11Context, wctx->wrappingkeylabel, &wrappingkeyhandle)) {
1937 	fprintf(stderr,"Error: could not find a public key with label '%s'\n", wctx->wrappingkeylabel);
1938 	rc = rc_error_object_not_found;
1939 	goto error;
1940     }
1941 
1942     /* if we called _wrap() with meth_keyhandle, then the wrappedkeylabel is NULL */
1943     /* and we can directly use the value in wrappedkeyhabndle */
1944     /* however we are still lacking the object class, so we retrieve it from the handle */
1945     if(wctx->wrappedkeylabel==NULL) {
1946 	wrappedkeyhandle = wctx->key[WRAPPEDKEYCTX_INNER_KEY_INDEX].wrappedkeyhandle;
1947 
1948 	/* extract object class from provided handle */
1949 	wrappedkeyobjclass = pkcs11_get_object_class(wctx->p11Context, wrappedkeyhandle);
1950 
1951 	if(wrappedkeyobjclass != CKO_SECRET_KEY && wrappedkeyobjclass != CKO_PRIVATE_KEY) {
1952 	    rc = rc_error_oops;
1953 	    goto error;
1954 	}
1955     } else {
1956 	/* we have a label, just retrieve handle and object class from label */
1957 	if(!pkcs11_findprivateorsecretkey(wctx->p11Context, wctx->wrappedkeylabel, &wrappedkeyhandle, &wrappedkeyobjclass)) {
1958 	    fprintf(stderr, "***Error: key with label '%s' does not exists\n", wctx->wrappedkeylabel);
1959 	    rc = rc_error_object_not_found;
1960 	    goto error;
1961 	}
1962     }
1963 
1964     /* step 1: setup wctx structure to remember the key handles */
1965     wctx->key[WRAPPEDKEYCTX_OUTER_KEY_INDEX].wrappingkeyhandle = wrappingkeyhandle;
1966     wctx->key[WRAPPEDKEYCTX_INNER_KEY_INDEX].wrappedkeyhandle = wrappedkeyhandle;
1967     wctx->key[WRAPPEDKEYCTX_INNER_KEY_INDEX].wrappedkeyobjclass = wrappedkeyobjclass;
1968 
1969     /* step 2: generate the intermediate temporary key */
1970     /* will be an AES for now */
1971 
1972     snprintf((char *)tempaes_label, sizeof tempaes_label, "tempaes-%ld", time(NULL));
1973 
1974     /* TODO - adapt to support other symmetric types - detect on wrapping alg */
1975     rc = pkcs11_genAES(wctx->p11Context,
1976 		       tempaes_label,
1977 		       256,
1978 		       tempaes_attrs,
1979 		       sizeof tempaes_attrs / sizeof(CK_ATTRIBUTE),
1980 		       &tempaes_handle,
1981 		       kg_session_for_wrapping);
1982 
1983     if(rc != rc_ok ) {
1984 	fprintf(stderr, "Unable to generate temporary wrapping key\n");
1985 	goto error;
1986     }
1987 
1988     /* step 3: remember our temporary key in wctx structure */
1989     wctx->key[WRAPPEDKEYCTX_OUTER_KEY_INDEX].wrappedkeyhandle = tempaes_handle;
1990     wctx->key[WRAPPEDKEYCTX_OUTER_KEY_INDEX].wrappedkeyobjclass = CKO_SECRET_KEY;
1991     wctx->key[WRAPPEDKEYCTX_INNER_KEY_INDEX].wrappingkeyhandle = tempaes_handle;
1992 
1993     /* step 4: wrap the inner key */
1994     switch(wctx->key[WRAPPEDKEYCTX_INNER_KEY_INDEX].wrapping_meth) {
1995     case w_cbcpad:
1996 	rc = _wrap_cbcpad(wctx);
1997 	break;
1998 
1999     case w_rfc3394:
2000 	rc = _wrap_rfc3394(wctx);
2001 	break;
2002 
2003     case w_rfc5649:
2004 	rc = _wrap_rfc5649(wctx);
2005 	break;
2006 
2007     default:
2008 	rc = rc_error_oops;
2009     }
2010 
2011     if(rc!=rc_ok) {
2012 	goto error;
2013     }
2014 
2015     /* step 5: wrap the outer key */
2016     switch(wctx->key[WRAPPEDKEYCTX_OUTER_KEY_INDEX].wrapping_meth) {
2017     case w_pkcs1_15:
2018 	rc = _wrap_pkcs1_15(wctx);
2019 	break;
2020 
2021     case w_pkcs1_oaep:
2022 	rc = _wrap_pkcs1_oaep(wctx);
2023 	break;
2024 
2025     default:
2026 	rc = rc_error_oops;
2027     }
2028 
2029     if(rc!=rc_ok) {
2030 	goto error;
2031     }
2032 
2033 error:
2034     if(tempaes_handle!=0) {
2035 	CK_RV rv = wctx->p11Context->FunctionList.C_DestroyObject(wctx->p11Context->Session, tempaes_handle);
2036 	if(rv != CKR_OK) {
2037 	    pkcs11_error( rv, "C_DestroyObject" );
2038 	}
2039     }
2040     return rc;
2041 
2042 }
2043 
2044 
2045 /*--------------------------------------------------------------------------------*/
2046 /* PUBLIC INTERFACE                                                               */
2047 /*--------------------------------------------------------------------------------*/
pkcs11_prepare_wrappingctx(wrappedKeyCtx * wctx,char * wrapjob)2048 func_rc pkcs11_prepare_wrappingctx(wrappedKeyCtx *wctx, char *wrapjob)
2049 {
2050 
2051     func_rc rc=rc_ok;
2052 
2053     if(wctx!=NULL && wrapjob!=NULL) {
2054 	int parserc;
2055 
2056 	/* http://stackoverflow.com/questions/1907847/how-to-use-yy-scan-string-in-lex     */
2057 	/* copy string into new buffer and Switch buffers*/
2058 	YY_BUFFER_STATE yybufstate = yy_scan_string(wrapjob);
2059 
2060 	/* parse string */
2061 	parserc = yyparse(wctx);
2062 
2063 	if(parserc!=0) {
2064 	    fprintf(stderr, "***Error scanning wrapping job string '%s'\n", wrapjob);
2065 	    rc =rc_error_invalid_argument;
2066 	}
2067 
2068 	/*Delete the new buffer*/
2069 	yy_delete_buffer(yybufstate);
2070     } else {
2071 	rc = rc_error_invalid_parameter_for_method;
2072     }
2073 
2074     return rc;
2075 }
2076 
_wrap(wrappedKeyCtx * wctx,wrap_source_method_t wrap_source_method,char * wrappedkeylabel,CK_OBJECT_HANDLE wrappedkeyhandle,CK_OBJECT_HANDLE pubkhandle)2077 static func_rc _wrap(wrappedKeyCtx *wctx,
2078 		     wrap_source_method_t wrap_source_method,
2079 		     char *wrappedkeylabel,
2080 		     CK_OBJECT_HANDLE wrappedkeyhandle,
2081 		     CK_OBJECT_HANDLE pubkhandle )
2082 {
2083     func_rc rc = rc_ok;
2084 
2085     /* keyindex: in case of envelope wrapping, the index shall always be the outer */
2086     int keyindex = wctx->is_envelope ? WRAPPEDKEYCTX_INNER_KEY_INDEX : WRAPPEDKEYCTX_LONE_KEY_INDEX;
2087 
2088     switch(wrap_source_method) {
2089     case meth_label:
2090 	wctx->wrappedkeylabel = strdup(wrappedkeylabel);
2091 	wctx->key[keyindex].wrappedkeyhandle = 0;
2092 	break;
2093 
2094     case meth_keyhandle:
2095 	wctx->wrappedkeylabel = NULL;
2096 	wctx->key[keyindex].wrappedkeyhandle = wrappedkeyhandle;
2097 	wctx->pubkhandle = pubkhandle;
2098 	break;
2099     }
2100 
2101     if(wctx->is_envelope) {
2102 	/* envelope wrapping */
2103 	rc = _wrap_envelope(wctx);
2104     } else {
2105 	switch(wctx->key[keyindex].wrapping_meth) {
2106 	case w_pkcs1_15:
2107 	    /* TODO: check if I can wrap */
2108 	    rc = _wrap_pkcs1_15(wctx);
2109 	    break;
2110 
2111 	case w_pkcs1_oaep:
2112 	    /* TODO: check if I can wrap */
2113 	    rc = _wrap_pkcs1_oaep(wctx);
2114 	    break;
2115 
2116 	case w_cbcpad:
2117 	    rc = _wrap_cbcpad(wctx);
2118 	    break;
2119 
2120 	case w_rfc3394:
2121 	    rc = _wrap_rfc3394(wctx);
2122 	    break;
2123 
2124 	case w_rfc5649:
2125 	    rc = _wrap_rfc5649(wctx);
2126 	    break;
2127 
2128 	default:
2129 	    rc = rc_error_unknown_wrapping_alg;
2130 	    fprintf(stderr, "Error: unsupported wrapping algorithm.\n");
2131 	}
2132     }
2133 
2134     return rc;
2135 }
2136 
2137 
pkcs11_output_wrapped_key(wrappedKeyCtx * wctx)2138 func_rc pkcs11_output_wrapped_key(wrappedKeyCtx *wctx)
2139 {
2140     func_rc rc = rc_ok;
2141     FILE *fp=stdout;
2142 
2143     if(wctx->filename) {
2144 	fp = fopen(wctx->filename, "w");
2145 	if(fp==NULL) {
2146 	    perror("***Warning: cannot write to file - will output to standard output");
2147 	    fp=stdout;
2148 	}
2149     }
2150 
2151     rc = _output_wrapped_key_header(wctx,fp);
2152     if(rc!=rc_ok) {
2153 	fprintf(stderr, "***Error: during wrapped key header creation\n");
2154 	goto error;
2155     }
2156 
2157     rc = _output_wrapped_key_attributes(wctx,fp);
2158     if(rc!=rc_ok) {
2159 	fprintf(stderr, "***Error: when outputing wrapped key attributes\n");
2160 	goto error;
2161     }
2162 
2163     rc = _output_wrapped_keys_b64(wctx,fp);
2164     if(rc!=rc_ok) {
2165 	fprintf(stderr, "***Error: when outputing wrapped key\n");
2166 	goto error;
2167     }
2168 
2169     /* do we have a handle to a public key? if so, output it as well */
2170     if(wctx->pubkhandle) {
2171 	rc = _output_public_key_attributes(wctx,fp);
2172 	if(rc!=rc_ok) {
2173 	    fprintf(stderr, "***Error: when outputing public key attributes\n");
2174 	    goto error;
2175 	}
2176 
2177 	rc = _output_public_key_b64(wctx,fp);
2178 	if(rc!=rc_ok) {
2179 	    fprintf(stderr, "***Error: when outputing public key\n");
2180 	    goto error;
2181 	}
2182     }
2183 
2184 error:
2185     if(fp && fp!=stdout) {
2186 	fclose(fp);
2187     }
2188     return rc;
2189 }
2190 
2191 
2192 
2193