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 /* pkcs11_pubk.c: module to implement p11importpubk */
20 /* import of a public key onto a PKCS#11 token      */
21 
22 #include <config.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <search.h>
27 #include <assert.h>
28 
29 #include <openssl/bio.h>
30 #include <openssl/pem.h>
31 #include <openssl/rsa.h>
32 #include <openssl/dh.h>
33 #include <openssl/dsa.h>
34 #include <openssl/ec.h>
35 
36 #include "pkcs11lib.h"
37 
38 /* prototypes */
39 
40 typedef enum e_pubk_source_type {
41     source_file,
42     source_buffer
43 } pubk_source_type;
44 
45 static int compare_CKA( const void *a, const void *b);
46 static EVP_PKEY * new_pubk_from_file(char *filename);
47 static EVP_PKEY * new_pubk_from_buffer(unsigned char *buffer, size_t len);
48 static CK_ULONG get_RSA_modulus(EVP_PKEY *pubkey, CK_BYTE_PTR *buf);
49 static CK_ULONG get_RSA_public_exponent(EVP_PKEY *pubkey, CK_BYTE_PTR *buf);
50 static CK_ULONG get_DH_prime(EVP_PKEY *pubkey, CK_BYTE_PTR *buf);
51 static CK_ULONG get_DH_base(EVP_PKEY *pubkey, CK_BYTE_PTR *buf);
52 static CK_ULONG get_DH_pubkey(EVP_PKEY *pubkey, CK_BYTE_PTR *buf);
53 static CK_ULONG get_DSA_prime(EVP_PKEY *pubkey, CK_BYTE_PTR *buf);
54 static CK_ULONG get_DSA_subprime(EVP_PKEY *pubkey, CK_BYTE_PTR *buf);
55 static CK_ULONG get_DSA_base(EVP_PKEY *pubkey, CK_BYTE_PTR *buf);
56 static CK_ULONG get_DSA_pubkey(EVP_PKEY *pubkey, CK_BYTE_PTR *buf);
57 static CK_ULONG get_EC_point(EVP_PKEY *pubkey, CK_BYTE_PTR *buf);
58 static CK_ULONG get_EC_params(EVP_PKEY *pubkey, CK_BYTE_PTR *buf);
59 static CK_ULONG get_ED_point(EVP_PKEY *pubkey, CK_BYTE_PTR *buf);
60 static CK_ULONG get_ED_params(EVP_PKEY *pubkey, CK_BYTE_PTR *buf);
61 static CK_ULONG get_EVP_PKEY_sha1(EVP_PKEY *pubkey, CK_BYTE_PTR *buf);
62 static CK_OBJECT_HANDLE _importpubk( pkcs11Context * p11Context,
63 				     char *filename,
64 				     unsigned char *buffer,
65 				     size_t len,
66 				     char *label,
67 				     CK_ATTRIBUTE attrs[],
68 				     CK_ULONG numattrs,
69 				     pubk_source_type source);
70 
71 
72 /* comparison function for attributes */
compare_CKA(const void * a,const void * b)73 static int compare_CKA( const void *a, const void *b)
74 {
75     return ((CK_ATTRIBUTE_PTR)a)->type == ((CK_ATTRIBUTE_PTR)b)->type ? 0 : -1;
76 }
77 
78 /* when importing a key, we want to skip these parameters from template */
is_attribute_skipped(const CK_ATTRIBUTE_TYPE attrib)79 static inline bool is_attribute_skipped( const CK_ATTRIBUTE_TYPE attrib)
80 {
81     return attrib==CKA_TOKEN || attrib==CKA_CLASS || attrib==CKA_KEY_TYPE;
82 }
83 
new_pubk_from_file(char * filename)84 static EVP_PKEY * new_pubk_from_file(char *filename)
85 {
86     EVP_PKEY * rv = NULL;
87     FILE *fp = NULL;
88 
89     fp = fopen(filename,"rb"); /* open in binary mode */
90 
91     if(fp) {
92 	EVP_PKEY *pubk;
93 
94 	/* try DER first */
95 	pubk = d2i_PUBKEY_fp(fp, NULL);
96 	fclose(fp);
97 
98 	if(pubk) {
99 	    puts("DER format detected");
100 	    rv = pubk;
101 	} else {
102 	    fp = fopen(filename,"r"); /* reopen in text mode */
103 
104 	    if(fp) {
105 		pubk = PEM_read_PUBKEY(fp, NULL, NULL, NULL);
106 		fclose(fp);
107 
108 		if(pubk) {
109 		    puts("PEM format detected");
110 		    rv = pubk;
111 		}
112 	    } else {
113 		perror("Error opening file");
114 	    }
115 	}
116     } else {
117 	perror("Error opening file");
118     }
119 
120     return rv;
121 }
122 
new_pubk_from_buffer(unsigned char * buffer,size_t len)123 static EVP_PKEY * new_pubk_from_buffer(unsigned char *buffer, size_t len)
124 {
125     EVP_PKEY * pubk = NULL;
126 
127     BIO *mem = BIO_new_mem_buf(buffer, len);
128 
129     pubk = d2i_PUBKEY_bio(mem, NULL);
130 
131     if(!pubk) {
132 	perror("Error when parsing public key");
133     }
134 
135     BIO_free(mem);
136 
137     return pubk;
138 }
139 
140 /* RSA */
141 
get_RSA_modulus(EVP_PKEY * pubkey,CK_BYTE_PTR * buf)142 static CK_ULONG get_RSA_modulus(EVP_PKEY *pubkey, CK_BYTE_PTR *buf) {
143     CK_ULONG rv = 0;
144 
145     if (pubkey && EVP_PKEY_base_id(pubkey) == EVP_PKEY_RSA) {
146 	RSA *rsa = EVP_PKEY_get0_RSA(pubkey);
147 	const BIGNUM *rsa_n;
148 	CK_BYTE_PTR p = NULL;
149 
150 	if (rsa == NULL) {
151 	    P_ERR();
152 	    goto error;
153 	}
154 	RSA_get0_key(rsa, &rsa_n, NULL, NULL);
155 	p = *buf = OPENSSL_malloc(BN_num_bytes(rsa_n));
156 
157 	if (*buf == NULL) {
158 	    P_ERR();
159 	    goto error;
160 	}
161 
162 	rv = BN_bn2bin(rsa_n, p);
163 
164 	/* if we fail here, we would free up requested memory */
165 	if (rv == 0) {
166 	    OPENSSL_free(*buf);
167 	    P_ERR();
168 	    goto error;
169 	}
170     }
171 error:
172     return rv;
173 }
174 
get_RSA_public_exponent(EVP_PKEY * pubkey,CK_BYTE_PTR * buf)175 static CK_ULONG get_RSA_public_exponent(EVP_PKEY *pubkey, CK_BYTE_PTR *buf) {
176     CK_ULONG rv = 0;
177 
178     if (pubkey && EVP_PKEY_base_id(pubkey) == EVP_PKEY_RSA) {
179 	RSA *rsa = EVP_PKEY_get0_RSA(pubkey);
180 	const BIGNUM *rsa_e;
181 	CK_BYTE_PTR p = NULL;
182 
183 	if (rsa == NULL) {
184 	    P_ERR();
185 	    goto error;
186 	}
187 	RSA_get0_key(rsa, NULL, &rsa_e, NULL);
188 	p = *buf = OPENSSL_malloc(BN_num_bytes(rsa_e));
189 
190 	if (*buf == NULL) {
191 	    P_ERR();
192 	    goto error;
193 	}
194 
195 	rv = BN_bn2bin(rsa_e, p);
196 
197 	/* if we fail here, we would free up requested memory */
198 	if (rv == 0) {
199 	    OPENSSL_free(*buf);
200 	    P_ERR();
201 	    goto error;
202 	}
203     }
204 error:
205     return rv;
206 }
207 
208 
209 
210 
211 /* DH */
212 
get_DH_prime(EVP_PKEY * pubkey,CK_BYTE_PTR * buf)213 static CK_ULONG get_DH_prime(EVP_PKEY *pubkey, CK_BYTE_PTR *buf) {
214     CK_ULONG rv = 0;
215 
216     if (pubkey && EVP_PKEY_base_id(pubkey) == EVP_PKEY_DH) {
217 	DH *dh = EVP_PKEY_get0_DH(pubkey);
218 	const BIGNUM *dh_p;
219 	CK_BYTE_PTR p = NULL;
220 
221 	if (dh == NULL) {
222 	    P_ERR();
223 	    goto error;
224 	}
225 	DH_get0_pqg(dh, &dh_p, NULL, NULL);
226 	p = *buf = OPENSSL_malloc(BN_num_bytes(dh_p));
227 
228 	if (*buf == NULL) {
229 	    P_ERR();
230 	    goto error;
231 	}
232 
233 	rv = BN_bn2bin(dh_p, p);
234 
235 	/* if we fail here, we would free up requested memory */
236 	if (rv == 0) {
237 	    OPENSSL_free(*buf);
238 	    P_ERR();
239 	    goto error;
240 	}
241     }
242 error:
243     return rv;
244 }
245 
246 
get_DH_base(EVP_PKEY * pubkey,CK_BYTE_PTR * buf)247 static CK_ULONG get_DH_base(EVP_PKEY *pubkey, CK_BYTE_PTR *buf) {
248     CK_ULONG rv = 0;
249 
250     if (pubkey && EVP_PKEY_base_id(pubkey) == EVP_PKEY_DH) {
251 	DH *dh = EVP_PKEY_get0_DH(pubkey);
252 	const BIGNUM *dh_g;
253 	CK_BYTE_PTR p = NULL;
254 
255 	if (dh == NULL) {
256 	    P_ERR();
257 	    goto error;
258 	}
259 	DH_get0_pqg(dh, NULL, NULL, &dh_g);
260 	p = *buf = OPENSSL_malloc(BN_num_bytes(dh_g));
261 
262 	if (*buf == NULL) {
263 	    P_ERR();
264 	    goto error;
265 	}
266 
267 	rv = BN_bn2bin(dh_g, p);
268 
269 	/* if we fail here, we would free up requested memory */
270 	if (rv == 0) {
271 	    OPENSSL_free(*buf);
272 	    P_ERR();
273 	    goto error;
274 	}
275     }
276 error:
277     return rv;
278 }
279 
get_DH_pubkey(EVP_PKEY * pubkey,CK_BYTE_PTR * buf)280 static CK_ULONG get_DH_pubkey(EVP_PKEY *pubkey, CK_BYTE_PTR *buf) {
281     CK_ULONG rv = 0;
282 
283     if (pubkey && EVP_PKEY_base_id(pubkey) == EVP_PKEY_DH) {
284 	DH *dh = EVP_PKEY_get0_DH(pubkey);
285 	const BIGNUM *dh_pub;
286 	CK_BYTE_PTR p = NULL;
287 
288 	if (dh == NULL) {
289 	    P_ERR();
290 	    goto error;
291 	}
292 	DH_get0_key(dh, &dh_pub, NULL);
293 	p = *buf = OPENSSL_malloc(BN_num_bytes(dh_pub));
294 
295 	if (*buf == NULL) {
296 	    P_ERR();
297 	    goto error;
298 	}
299 
300 	rv = BN_bn2bin(dh_pub, p);
301 
302 	/* if we fail here, we would free up requested memory */
303 	if (rv == 0) {
304 	    OPENSSL_free(*buf);
305 	    P_ERR();
306 	    goto error;
307 	}
308     }
309 error:
310     return rv;
311 }
312 
313 /* DSA */
314 
get_DSA_prime(EVP_PKEY * pubkey,CK_BYTE_PTR * buf)315 static CK_ULONG get_DSA_prime(EVP_PKEY *pubkey, CK_BYTE_PTR *buf) {
316     CK_ULONG rv = 0;
317 
318     if (pubkey && EVP_PKEY_base_id(pubkey) == EVP_PKEY_DSA) {
319 	DSA *dsa = EVP_PKEY_get0_DSA(pubkey);
320 	const BIGNUM *dsa_p;
321 	CK_BYTE_PTR p = NULL;
322 
323 	if (dsa == NULL) {
324 	    P_ERR();
325 	    goto error;
326 	}
327 	DSA_get0_pqg(dsa, &dsa_p, NULL, NULL);
328 	p = *buf = OPENSSL_malloc(BN_num_bytes(dsa_p));
329 
330 	if (*buf == NULL) {
331 	    P_ERR();
332 	    goto error;
333 	}
334 
335 	rv = BN_bn2bin(dsa_p, p);
336 
337 	/* if we fail here, we would free up requested memory */
338 	if (rv == 0) {
339 	    OPENSSL_free(*buf);
340 	    P_ERR();
341 	    goto error;
342 	}
343     }
344 error:
345     return rv;
346 }
347 
get_DSA_subprime(EVP_PKEY * pubkey,CK_BYTE_PTR * buf)348 static CK_ULONG get_DSA_subprime(EVP_PKEY *pubkey, CK_BYTE_PTR *buf) {
349     CK_ULONG rv = 0;
350 
351     if (pubkey && EVP_PKEY_base_id(pubkey) == EVP_PKEY_DSA) {
352 	DSA *dsa = EVP_PKEY_get0_DSA(pubkey);
353 	const BIGNUM *dsa_q;
354 	CK_BYTE_PTR p = NULL;
355 
356 	if (dsa == NULL) {
357 	    P_ERR();
358 	    goto error;
359 	}
360 	DSA_get0_pqg(dsa, NULL, &dsa_q, NULL);
361 	p = *buf = OPENSSL_malloc(BN_num_bytes(dsa_q));
362 
363 	if (*buf == NULL) {
364 	    P_ERR();
365 	    goto error;
366 	}
367 
368 	rv = BN_bn2bin(dsa_q, p);
369 
370 	/* if we fail here, we would free up requested memory */
371 	if (rv == 0) {
372 	    OPENSSL_free(*buf);
373 	    P_ERR();
374 	    goto error;
375 	}
376     }
377 error:
378     return rv;
379 }
380 
get_DSA_base(EVP_PKEY * pubkey,CK_BYTE_PTR * buf)381 static CK_ULONG get_DSA_base(EVP_PKEY *pubkey, CK_BYTE_PTR *buf) {
382     CK_ULONG rv = 0;
383 
384     if (pubkey && EVP_PKEY_base_id(pubkey) == EVP_PKEY_DSA) {
385 	DSA *dsa = EVP_PKEY_get0_DSA(pubkey);
386 	const BIGNUM *dsa_g;
387 	CK_BYTE_PTR p = NULL;
388 
389 	if (dsa == NULL) {
390 	    P_ERR();
391 	    goto error;
392 	}
393 	DSA_get0_pqg(dsa, NULL, NULL, &dsa_g);
394 	p = *buf = OPENSSL_malloc(BN_num_bytes(dsa_g));
395 
396 	if (*buf == NULL) {
397 	    P_ERR();
398 	    goto error;
399 	}
400 
401 	rv = BN_bn2bin(dsa_g, p);
402 
403 	/* if we fail here, we would free up requested memory */
404 	if (rv == 0) {
405 	    OPENSSL_free(*buf);
406 	    P_ERR();
407 	    goto error;
408 	}
409     }
410 error:
411     return rv;
412 }
413 
get_DSA_pubkey(EVP_PKEY * pubkey,CK_BYTE_PTR * buf)414 static CK_ULONG get_DSA_pubkey(EVP_PKEY *pubkey, CK_BYTE_PTR *buf) {
415     CK_ULONG rv = 0;
416 
417     if (pubkey && EVP_PKEY_base_id(pubkey) == EVP_PKEY_DSA) {
418 	DSA *dsa = EVP_PKEY_get0_DSA(pubkey);
419 	const BIGNUM *dsa_pubkey;
420 	CK_BYTE_PTR p = NULL;
421 
422 	if (dsa == NULL) {
423 	    P_ERR();
424 	    goto error;
425 	}
426 	DSA_get0_key(dsa, &dsa_pubkey, NULL);
427 	p = *buf = OPENSSL_malloc(BN_num_bytes(dsa_pubkey));
428 
429 	if (*buf == NULL) {
430 	    P_ERR();
431 	    goto error;
432 	}
433 
434 	rv = BN_bn2bin(dsa_pubkey, p);
435 
436 	/* if we fail here, we would free up requested memory */
437 	if (rv == 0) {
438 	    OPENSSL_free(*buf);
439 	    P_ERR();
440 	    goto error;
441 	}
442     }
443 error:
444     return rv;
445 }
446 
447 
448 /* EC */
449 
get_EC_point(EVP_PKEY * pubkey,CK_BYTE_PTR * buf)450 static CK_ULONG get_EC_point(EVP_PKEY *pubkey, CK_BYTE_PTR *buf)
451 {
452     CK_ULONG rv=0;
453     EC_KEY* ec=NULL;
454     int i2dlen=0;
455     unsigned char *octp = NULL, *octbuf = NULL;
456 
457     if ( pubkey && EVP_PKEY_base_id(pubkey)==EVP_PKEY_EC  ) {
458 
459 	ec = EVP_PKEY_get0_EC_KEY(pubkey);
460 
461 	if(ec==NULL) {
462 	    P_ERR();
463 	    goto error;
464 	}
465 
466 	const EC_POINT *ec_point = EC_KEY_get0_public_key(ec);
467 	/* get0 means no ref counter is incremented */
468 
469 	if(ec_point==NULL) {
470 	    P_ERR();
471 	    goto error;
472 	}
473 
474 	const EC_GROUP *ec_group = EC_KEY_get0_group(ec);
475 	/* get0 means no ref counter is incremented */
476 
477 	if(ec_group==NULL) {
478 	    P_ERR();
479 	    goto error;
480 	}
481 
482 	size_t octbuflen = EC_POINT_point2oct(ec_group, ec_point,
483 					      POINT_CONVERSION_UNCOMPRESSED,
484 					      NULL, 0, NULL);
485 
486 	if(octbuflen==0) {
487 	    P_ERR();
488 	    goto error;
489 	}
490 
491 	octp = octbuf = OPENSSL_malloc( octbuflen );
492 
493 	if(octbuf==NULL) {
494 	    P_ERR();
495 	    goto error;
496 	}
497 
498 	rv = (CK_ULONG) EC_POINT_point2oct(ec_group, ec_point,
499 					   POINT_CONVERSION_UNCOMPRESSED,
500 					   octp, octbuflen, NULL);
501 
502 	if(rv==0) {
503 	    P_ERR();
504 	    OPENSSL_free(buf);
505 	    goto error;
506 	}
507 
508 	/* DER-encoded of point in octbuf  */
509 	/* now wrap this into OCTET_STRING */
510 
511 	ASN1_OCTET_STRING *wrapped = ASN1_OCTET_STRING_new();
512 
513 	if(wrapped==NULL) {
514 	    P_ERR();
515 	    goto error;
516 	}
517 
518 	if( ASN1_STRING_set(wrapped, octbuf, octbuflen) == 0 ) {
519 	    P_ERR();
520 	    goto error;
521 	}
522 
523 	/* wrapped contains the data we need to set into buf */
524 
525 	i2dlen = i2d_ASN1_OCTET_STRING(wrapped, NULL);
526 
527 	if(i2dlen<0) {
528 	    P_ERR();
529 	    goto error;
530 	}
531 
532 	CK_BYTE_PTR p = NULL;
533 
534 	*buf = OPENSSL_malloc(i2dlen);
535 
536 	if(*buf==NULL) {
537 	    P_ERR();
538 	    goto error;
539 	}
540 
541 	p = *buf;
542 
543 	i2dlen = i2d_ASN1_OCTET_STRING(wrapped, &p);
544 
545 	if(i2dlen<0) {
546 	    P_ERR();
547 	    goto error;
548 	}
549 
550 	rv = i2dlen;
551     }
552 error:
553     if(octbuf != NULL) { OPENSSL_free(octbuf); }
554 
555     return rv;
556 }
557 
558 
559 
get_EC_params(EVP_PKEY * pubkey,CK_BYTE_PTR * buf)560 static CK_ULONG get_EC_params(EVP_PKEY *pubkey, CK_BYTE_PTR *buf)
561 {
562     CK_LONG rv=0;
563     EC_KEY* ec=NULL;
564 
565     if ( pubkey && EVP_PKEY_base_id(pubkey)==EVP_PKEY_EC  ) {
566 
567 	ec = EVP_PKEY_get0_EC_KEY(pubkey);
568 
569 	if(ec==NULL) {
570 	    P_ERR();
571 	    goto error;
572 	}
573 
574 	const EC_GROUP *ec_group = EC_KEY_get0_group(ec);
575 	/* get0 means no ref counter is incremented */
576 
577 	if(ec_group==NULL) {
578 	    P_ERR();
579 	    goto error;
580 	}
581 
582 	*buf = NULL;		/* clearing it */
583 
584 	rv = i2d_ECPKParameters(ec_group, buf);
585 
586 	if(rv<0) {
587 	    P_ERR();
588 	    goto error;
589 	}
590 
591     }
592 error:
593     return rv<0 ? 0 : rv ;
594 }
595 
596 /* get_ED_point is merely a hack                                               */
597 /* this is because EDWARDS curves are not well supported in OpenSSL            */
598 /* while there is an EVP interface, there is no low-level PKEY or EC interface */
599 /* we assume here that only two curves are supported: ED25519 and ED448        */
600 /* the hack consists of encoding the key, then extract the point based on a    */
601 /* hardcoded offset. Ugly but works. Any other suggestion welcome.             */
get_ED_point(EVP_PKEY * pubkey,CK_BYTE_PTR * buf)602 static CK_ULONG get_ED_point(EVP_PKEY *pubkey, CK_BYTE_PTR *buf)
603 {
604     CK_ULONG rv=0;
605     uint8_t *pkeybuf = NULL;
606     X509_PUBKEY *x509_pk = NULL;
607     ASN1_OCTET_STRING *point = NULL;
608     const uint8_t *p;
609     int len;
610 
611     len = i2d_PUBKEY(pubkey, &pkeybuf);
612     if(len<0) {
613 	P_ERR();
614 	goto error;
615     }
616 
617     /* trick: convert back to X509_PUBKEY */
618     p = pkeybuf;
619     x509_pk = d2i_X509_PUBKEY(NULL, &p, len);
620     if(!x509_pk) {
621 	P_ERR();
622 	goto error;
623     }
624 
625     const uint8_t *pk;
626     int pklen;
627 
628     X509_PUBKEY_get0_param(NULL, &pk, &pklen, NULL, x509_pk); /* nothing to test, always returns 1 */
629 
630     if( (point = ASN1_OCTET_STRING_new()) == NULL ) {
631 	P_ERR();
632 	goto error;
633     }
634     ASN1_OCTET_STRING_set(point, pk, pklen); /* assign */
635 
636     len = i2d_ASN1_OCTET_STRING(point, buf);
637     if(len<0) {
638 	P_ERR();
639 	goto error;
640     }
641 
642     rv = len;
643 
644 error:
645     if(point) { ASN1_OCTET_STRING_free(point); }
646     if(x509_pk) { X509_PUBKEY_free(x509_pk); }
647     if(pkeybuf) { OPENSSL_free(pkeybuf); }
648     return rv;
649 }
650 
get_ED_params(EVP_PKEY * pubkey,CK_BYTE_PTR * buf)651 static CK_ULONG get_ED_params(EVP_PKEY *pubkey, CK_BYTE_PTR *buf)
652 {
653     CK_ULONG rv = 0;
654     ASN1_OBJECT *obj = NULL;
655 
656     obj = OBJ_nid2obj(EVP_PKEY_base_id(pubkey));
657     if(!obj) {
658 	P_ERR();
659 	goto error;
660     }
661 
662     assert( *buf == NULL );		/* make sure we point to nowhere */
663     int len = i2d_ASN1_OBJECT(obj, buf);
664     if(len<0) {
665 	P_ERR();
666 	goto error;
667     }
668 
669     rv = len;
670 
671 error:
672     if(obj) { ASN1_OBJECT_free(obj); }
673     return rv;
674 }
675 
676 
677 /*  get_EVP_PKEY_sha1: will retrieve RSA public key and compute SHA-1 digest
678     on modulus, represented as big-endian binary digit,
679     with no leading 0x00.
680     This is what IBM JCE provider for PKCS#11 uses for setting CKA_ID.
681 
682     for DSA and DH, SHA-1 digest of CKA_PUBKEY is used instead.
683     for EC, SHA-1 digest of CKA_EC_POINT is used instead (uncompressed form).
684 
685 */
686 
687 
get_EVP_PKEY_sha1(EVP_PKEY * pubkey,CK_BYTE_PTR * buf)688 static CK_ULONG get_EVP_PKEY_sha1(EVP_PKEY *pubkey, CK_BYTE_PTR *buf) {
689 
690     CK_ULONG rv = 0;
691     if (pubkey && buf) {
692 	switch (EVP_PKEY_base_id(pubkey)) {
693 
694 	case EVP_PKEY_RSA: {
695 	    RSA *rsa;
696 	    const BIGNUM *rsa_n;
697 
698 	    rsa = EVP_PKEY_get0_RSA(pubkey);
699 	    if (rsa) {
700 		RSA_get0_key(rsa, &rsa_n, NULL, NULL);
701 		CK_BYTE_PTR bn_buf = OPENSSL_malloc(BN_num_bytes(rsa_n)); /* we allocate before converting */
702 		if (bn_buf) {
703 		    int bn_buf_len = BN_bn2bin(rsa_n, bn_buf);
704 		    {
705 			/* SHA-1 block */
706 			EVP_MD_CTX *mdctx;
707 			const EVP_MD *md;
708 			unsigned int md_len;
709 
710 			*buf = OPENSSL_malloc(SHA_DIGEST_LENGTH); /* we allocate the buffer, and return it. */
711 
712 			if (*buf) {
713 			    md = EVP_sha1();
714 			    mdctx = EVP_MD_CTX_create();
715 			    EVP_DigestInit_ex(mdctx, md, NULL);
716 			    EVP_DigestUpdate(mdctx, bn_buf, bn_buf_len);
717 			    EVP_DigestFinal_ex(mdctx, *buf, &md_len);
718 			    EVP_MD_CTX_destroy(mdctx);
719 			    rv = md_len;
720 			}
721 		    }
722 		    OPENSSL_free(bn_buf);
723 		}
724 	    }
725 	}
726 	    break;
727 
728 
729 	case EVP_PKEY_DSA: {
730 	    DSA *dsa;
731 	    const BIGNUM *dsa_pub_key;
732 
733 	    dsa = EVP_PKEY_get0_DSA(pubkey);
734 	    if (dsa) {
735 		DSA_get0_key(dsa, &dsa_pub_key, NULL);
736 		CK_BYTE_PTR bn_buf = OPENSSL_malloc(BN_num_bytes(dsa_pub_key)); /* we allocate before converting */
737 		if (bn_buf) {
738 		    int bn_buf_len = BN_bn2bin(dsa_pub_key, bn_buf);
739 		    {
740 			/* SHA-1 block */
741 			EVP_MD_CTX *mdctx;
742 			const EVP_MD *md;
743 			unsigned int md_len;
744 
745 			*buf = OPENSSL_malloc(SHA_DIGEST_LENGTH); /* we allocate the buffer, and return it. */
746 
747 			if (*buf) {
748 			    md = EVP_sha1();
749 			    mdctx = EVP_MD_CTX_create();
750 			    EVP_DigestInit_ex(mdctx, md, NULL);
751 			    EVP_DigestUpdate(mdctx, bn_buf, bn_buf_len);
752 			    EVP_DigestFinal_ex(mdctx, *buf, &md_len);
753 			    EVP_MD_CTX_destroy(mdctx);
754 			    rv = md_len;
755 			}
756 		    }
757 		    OPENSSL_free(bn_buf);
758 		}
759 	    }
760 	}
761 	    break;
762 
763 	    /* for EC, we need to retrieve the points (uncompressed), then encapsulate into an OCTETSTRING */
764 	    /* which corresponds to the encoding on PKCS#11 */
765 	case EVP_PKEY_EC: {
766 	    EC_KEY *ec;
767 
768 	    ec = EVP_PKEY_get0_EC_KEY(pubkey);
769 	    if (ec == NULL) {
770 		P_ERR();
771 	    } else {
772 		const EC_POINT *ec_point = EC_KEY_get0_public_key(ec);
773 		const EC_GROUP *ec_group = EC_KEY_get0_group(ec);
774 
775 
776 		if (ec_point == NULL) {
777 		    P_ERR();
778 		} else if (ec_group == NULL) {
779 		    P_ERR();
780 		} else {
781 
782 		    /* first call to assess length of target buffer */
783 		    size_t ec_buflen = EC_POINT_point2oct(ec_group, ec_point,
784 							  POINT_CONVERSION_UNCOMPRESSED,
785 							  NULL, 0, NULL);
786 
787 		    if (ec_buflen == 0) {
788 			P_ERR();
789 		    } else {
790 
791 			unsigned char *p, *ec_buf;
792 
793 			p = ec_buf = OPENSSL_malloc(ec_buflen);
794 
795 			if (ec_buf == NULL) {
796 			    P_ERR();
797 			} else {
798 			    /* second call to obtain DER-encoded point */
799 			    rv = (CK_ULONG) EC_POINT_point2oct(ec_group, ec_point,
800 							       POINT_CONVERSION_UNCOMPRESSED,
801 							       p, ec_buflen, NULL);
802 			    if (rv == 0) {
803 				P_ERR();
804 			    } else {
805 
806 				/* now start the wrapping to OCTET STRING business */
807 
808 				ASN1_OCTET_STRING *wrapped = ASN1_OCTET_STRING_new();
809 
810 				if (wrapped == NULL) {
811 				    P_ERR();
812 				} else {
813 				    if (ASN1_STRING_set(wrapped, ec_buf, ec_buflen) == 0) {
814 					P_ERR();
815 				    } else {
816 					/* wrapped contains the data we need to set into buf */
817 
818 					/* determine length of buffer */
819 					int i2dlen = i2d_ASN1_OCTET_STRING(wrapped, NULL);
820 
821 					if (i2dlen < 0) {
822 					    P_ERR();
823 					} else {
824 
825 					    CK_BYTE_PTR p = NULL, wrapbuf = NULL;
826 
827 					    wrapbuf = OPENSSL_malloc(i2dlen);
828 
829 					    if (wrapbuf == NULL) {
830 						P_ERR();
831 					    } else {
832 
833 						p = wrapbuf;
834 
835 						i2dlen = i2d_ASN1_OCTET_STRING(wrapped, &p);
836 
837 						if (i2dlen < 0) {
838 						    P_ERR();
839 						} else {
840 
841 						    /* SHA-1 block */
842 						    EVP_MD_CTX *mdctx;
843 						    const EVP_MD *md;
844 						    unsigned int md_len;
845 
846 						    *buf = OPENSSL_malloc(SHA_DIGEST_LENGTH); /* we allocate the buffer, and return it. */
847 
848 						    if (*buf == NULL) {
849 							P_ERR();
850 						    } else {
851 							md = EVP_sha1();
852 							mdctx = EVP_MD_CTX_create();
853 							EVP_DigestInit_ex(mdctx, md, NULL);
854 							EVP_DigestUpdate(mdctx, wrapbuf, i2dlen);
855 							EVP_DigestFinal_ex(mdctx, *buf, &md_len);
856 							EVP_MD_CTX_destroy(mdctx);
857 							rv = md_len;
858 						    }
859 						}
860 					    }
861 					    OPENSSL_free(wrapbuf);
862 					}
863 				    }
864 				    ASN1_OCTET_STRING_free(wrapped);
865 				}
866 
867 			    }
868 			    OPENSSL_free(ec_buf);
869 			}
870 		    }
871 		    /* get0 on ec_point & ec_group, we can safely forget */
872 		}
873 		EC_KEY_free(ec);
874 	    }
875 	}
876 	    break;
877 
878 	case EVP_PKEY_ED25519:
879 	case EVP_PKEY_ED448: {
880 	    CK_BYTE_PTR point = NULL;
881 	    CK_ULONG point_len;
882 
883 	    point_len = get_ED_point(pubkey, &point); /* get octet-string */
884 	    if(point_len>0) {
885 		/* SHA-1 block */
886 		EVP_MD_CTX *mdctx;
887 		const EVP_MD *md;
888 		unsigned int md_len;
889 
890 		*buf = OPENSSL_malloc(SHA_DIGEST_LENGTH); /* we allocate the buffer, and return it. */
891 
892 		if (*buf == NULL) {
893 		    P_ERR();
894 		} else {
895 		    md = EVP_sha1();
896 		    mdctx = EVP_MD_CTX_create();
897 		    EVP_DigestInit_ex(mdctx, md, NULL);
898 		    EVP_DigestUpdate(mdctx, point, point_len);
899 		    EVP_DigestFinal_ex(mdctx, *buf, &md_len);
900 		    EVP_MD_CTX_destroy(mdctx);
901 		    rv = md_len;
902 		}
903 		OPENSSL_free(point);
904 	    }
905 	}
906 	    break;
907 
908 
909 	case EVP_PKEY_DH: {
910 	    DH *dh;
911 	    const BIGNUM *dh_pub_key;
912 
913 	    dh = EVP_PKEY_get0_DH(pubkey);
914 	    if (dh) {
915 		DH_get0_key(dh, &dh_pub_key, NULL);
916 		CK_BYTE_PTR bn_buf = OPENSSL_malloc(BN_num_bytes(dh_pub_key)); /* we allocate before converting */
917 		if (bn_buf) {
918 		    int bn_buf_len = BN_bn2bin(dh_pub_key, bn_buf);
919 		    {
920 			/* SHA-1 block */
921 			EVP_MD_CTX *mdctx;
922 			const EVP_MD *md;
923 			unsigned int md_len;
924 
925 			*buf = OPENSSL_malloc(SHA_DIGEST_LENGTH); /* we allocate the buffer, and return it. */
926 
927 			if (*buf) {
928 			    md = EVP_sha1();
929 			    mdctx = EVP_MD_CTX_create();
930 			    EVP_DigestInit_ex(mdctx, md, NULL);
931 			    EVP_DigestUpdate(mdctx, bn_buf, bn_buf_len);
932 			    EVP_DigestFinal_ex(mdctx, *buf, &md_len);
933 			    EVP_MD_CTX_destroy(mdctx);
934 			    rv = md_len;
935 			}
936 		    }
937 		    OPENSSL_free(bn_buf);
938 		}
939 	    }
940 	}
941 	    break;
942 
943 	default:
944 	    break;
945 
946 	}
947     }
948     return rv;
949 }
950 
_importpubk(pkcs11Context * p11Context,char * filename,unsigned char * buffer,size_t len,char * label,CK_ATTRIBUTE attrs[],CK_ULONG numattrs,pubk_source_type source)951 static CK_OBJECT_HANDLE _importpubk( pkcs11Context * p11Context,
952 				     char *filename,
953 				     unsigned char *buffer,
954 				     size_t len,
955 				     char *label,
956 				     CK_ATTRIBUTE attrs[],
957 				     CK_ULONG numattrs,
958 				     pubk_source_type source
959     )
960 {
961 
962     CK_OBJECT_HANDLE pubkhandle = NULL_PTR;
963 
964     CK_RV retCode;
965     CK_OBJECT_CLASS pubkClass = CKO_PUBLIC_KEY;
966     CK_KEY_TYPE pubkType;
967 
968     CK_BBOOL ck_false = CK_FALSE;
969     CK_BBOOL ck_true = CK_TRUE;
970 
971     EVP_PKEY *pubk = NULL;
972     size_t i;
973 
974     /* When importing a public key, two cases are supported:
975      * - importing a public key from `p11importpubk`
976      *   in this case, there is a 'default' template that creates useful public keys
977      *   that template is then adjusted using attributes given at the command line
978      *
979      * - importing a public key from `p11unwrap`
980      *   in this case, the default template is "pristine", and is adjusted using
981      *   what is provided from the wrap file. This is to ensure that no attibute
982      *   is enabled by mistake.
983      *
984      */
985 
986     switch(source) {
987     case source_file:
988 	if(!filename) {
989 	    fprintf(stderr, "***Filename not specified for public key\n");
990 	    break;
991 	}
992 	pubk = new_pubk_from_file(filename);
993 	break;
994 
995     case source_buffer:
996 	if(!buffer) {
997 	    fprintf(stderr, "***no buffer provided for public key\n");
998 	    break;
999 	}
1000 	pubk = new_pubk_from_buffer(buffer, len);
1001 	break;
1002 
1003     default:
1004 	fprintf(stderr, "***internal error\n");
1005     };
1006 
1007     if(pubk) {
1008 
1009 	switch( EVP_PKEY_base_id(pubk) ) {
1010 
1011 	case EVP_PKEY_RSA: {
1012 	    CK_BYTE_PTR pubkey_hash = NULL;
1013 	    CK_ULONG pubkey_hash_len = 0;
1014 
1015 	    CK_BYTE_PTR rsa_modulus = NULL;
1016 	    CK_ULONG rsa_modulus_len = 0;
1017 
1018 	    CK_BYTE_PTR rsa_public_exponent = NULL;
1019 	    CK_ULONG rsa_public_exponent_len =0;
1020 
1021 	    CK_ATTRIBUTE pubktemplate[] = {
1022 		{CKA_CLASS, &pubkClass, sizeof pubkClass},       /* 0  */
1023 		{CKA_KEY_TYPE, &pubkType, sizeof pubkType},      /* 1  */
1024 		{CKA_ID, NULL, 0},				 /* 2  */
1025 		{CKA_LABEL, label, label ? strlen(label) : 0 },	 /* 3  */
1026 		{CKA_ENCRYPT, source == source_file ? &ck_true : &ck_false, sizeof ck_false },	 /* 4  */
1027 		{CKA_WRAP,    source == source_file ? &ck_true : &ck_false, sizeof ck_false },	 /* 5  */
1028 		{CKA_VERIFY,  source == source_file ? &ck_true : &ck_false, sizeof ck_false },	 /* 6  */
1029 		{CKA_TOKEN, &ck_true, sizeof ck_true },		 /* 7  */
1030 		{CKA_MODULUS, NULL, 0 },                         /* 8  */
1031 		{CKA_PUBLIC_EXPONENT, NULL, 0 },                 /* 9 */
1032 		/* leave room for up to 12 additional attributes */
1033 		{0L, NULL, 0L},
1034 		{0L, NULL, 0L},
1035 		{0L, NULL, 0L},
1036 		{0L, NULL, 0L},
1037 		{0L, NULL, 0L},
1038 		{0L, NULL, 0L},
1039 		{0L, NULL, 0L},
1040 		{0L, NULL, 0L},
1041 		{0L, NULL, 0L},
1042 		{0L, NULL, 0L},
1043 		{0L, NULL, 0L},
1044 		{0L, NULL, 0L},
1045 	    };
1046 
1047 	    size_t pubk_template_len_max = (sizeof(pubktemplate)/sizeof(CK_ATTRIBUTE));
1048 	    size_t pubk_template_len_min = pubk_template_len_max - 12;
1049 	    size_t pubk_num_elems = pubk_template_len_min;
1050 
1051 	    pubkType = CKK_RSA;
1052 	    pubkey_hash_len = get_EVP_PKEY_sha1( pubk, &pubkey_hash);
1053 
1054 	    rsa_modulus_len = get_RSA_modulus( pubk, &rsa_modulus);
1055 	    rsa_public_exponent_len = get_RSA_public_exponent( pubk, &rsa_public_exponent);
1056 
1057 	    if(rsa_modulus_len>0 && rsa_public_exponent_len>0) {
1058 
1059 		/* we have everything, let's fill in the template */
1060 
1061 		pubktemplate[2].pValue = pubkey_hash; /* CKA_ID */
1062 		pubktemplate[2].ulValueLen = pubkey_hash_len;
1063 
1064 		pubktemplate[8].pValue = rsa_modulus;
1065 		pubktemplate[8].ulValueLen = rsa_modulus_len;
1066 
1067 		pubktemplate[9].pValue = rsa_public_exponent;
1068 		pubktemplate[9].ulValueLen = rsa_public_exponent_len;
1069 
1070 		for(i=0; i<numattrs && pubk_num_elems<pubk_template_len_max; i++)
1071 		{
1072 		    switch(attrs[i].type) {
1073 		    case CKA_LABEL:
1074 		    case CKA_ID:
1075 		    case CKA_ENCRYPT:
1076 		    case CKA_WRAP:
1077 		    case CKA_VERIFY:
1078 		    case CKA_VERIFY_RECOVER: /* not in template onwards */
1079 		    case CKA_DERIVE:
1080 		    case CKA_TRUSTED:
1081 		    case CKA_PRIVATE:
1082 		    case CKA_WRAP_TEMPLATE:
1083 		    case CKA_COPYABLE:
1084 		    case CKA_MODIFIABLE:
1085 		    case CKA_DESTROYABLE:
1086 		    case CKA_START_DATE:
1087 		    case CKA_END_DATE:
1088 		    case CKA_SUBJECT:
1089 		    case CKA_PUBLIC_KEY_INFO:
1090 		    {
1091 			size_t next_pubk_num_elems = pubk_num_elems;
1092 
1093 			CK_ATTRIBUTE_PTR match = lsearch( &attrs[i],
1094 							  pubktemplate,
1095 							  &next_pubk_num_elems,
1096 							  sizeof(CK_ATTRIBUTE),
1097 							  compare_CKA );
1098 
1099 			/* if we have a match and the record was not created by lsearch */
1100 			/* steal the pointer from attrs array. */
1101 			/* It's OK as the template is sitting on the stack, no need */
1102 			/* to dealloc when leaving scope  */
1103 			if(match) {
1104 			    if(next_pubk_num_elems==pubk_num_elems) {
1105 				match->pValue = attrs[i].pValue;           /* copy pointer */
1106 				match->ulValueLen = attrs[i].ulValueLen;   /* adjust length */
1107 			    }
1108 			    else {
1109 				/* everything was copied by lsearch */
1110 				/* just increment array length */
1111 				pubk_num_elems = next_pubk_num_elems;
1112 			    }
1113 			} else {
1114 			    fprintf(stderr, "***Error: can't update attribute array - skipping 0x%08lx\n", attrs[i].type);
1115 			    /* TODO print attribute text */
1116 			}
1117 		    }
1118 		    break;
1119 
1120 		    default:
1121 			if(!is_attribute_skipped(attrs[i].type)) {
1122 			    fprintf(stderr, "***Warning: attribute 0x%08lx skipped\n", attrs[i].type);
1123 			    /* pass */
1124 			}
1125 			break;
1126 		    }
1127 		}
1128 
1129 		retCode = p11Context->FunctionList.C_CreateObject(p11Context->Session,
1130 								  pubktemplate,
1131 								  pubk_num_elems,
1132 								  &pubkhandle);
1133 
1134 		if(retCode!=CKR_OK) {
1135 		    pkcs11_error( retCode, "CreateObject" );
1136 		}
1137 
1138 		/* if we are here, we have to free up memory anyway */
1139 	    }
1140 
1141 	    if(pubkey_hash) { OPENSSL_free(pubkey_hash); }
1142 	    if(rsa_modulus) { OPENSSL_free(rsa_modulus); }
1143 	    if(rsa_public_exponent) { OPENSSL_free(rsa_public_exponent); }
1144 	}
1145 	    break;
1146 
1147 	case EVP_PKEY_DSA: {
1148 	    CK_BYTE_PTR pubkey_hash = NULL;
1149 	    CK_ULONG pubkey_hash_len = 0;
1150 
1151 	    CK_BYTE_PTR dsa_prime = NULL;
1152 	    CK_ULONG dsa_prime_len = 0;
1153 
1154 	    CK_BYTE_PTR dsa_subprime = NULL;
1155 	    CK_ULONG dsa_subprime_len = 0;
1156 
1157 	    CK_BYTE_PTR dsa_base = NULL;
1158 	    CK_ULONG dsa_base_len = 0;
1159 
1160 	    CK_BYTE_PTR dsa_pubkey = NULL;
1161 	    CK_ULONG dsa_pubkey_len = 0;
1162 
1163 
1164 	    CK_ATTRIBUTE pubktemplate[] = {
1165 		{CKA_CLASS, &pubkClass, sizeof pubkClass},           /* 0  */
1166 		{CKA_KEY_TYPE, &pubkType, sizeof pubkType},	     /* 1  */
1167 		{CKA_ID, NULL, 0},				     /* 2  */
1168 		{CKA_LABEL, label, label ? strlen(label) : 0 },	     /* 3  */
1169 		{CKA_VERIFY, source == source_file ? &ck_true : &ck_false, sizeof ck_false }, /* 4  */
1170 		{CKA_TOKEN, &ck_true, sizeof ck_true},		     /* 5  */
1171 		{CKA_PRIME, NULL, 0 },                               /* 6  */
1172 		{CKA_SUBPRIME, NULL, 0 },                            /* 7  */
1173 		{CKA_BASE, NULL, 0 },                                /* 8  */
1174 		{CKA_VALUE, NULL, 0 },                               /* 9  */
1175 		/* leave room for up to 12 additional attributes */
1176 		{0L, NULL, 0L},
1177 		{0L, NULL, 0L},
1178 		{0L, NULL, 0L},
1179 		{0L, NULL, 0L},
1180 		{0L, NULL, 0L},
1181 		{0L, NULL, 0L},
1182 		{0L, NULL, 0L},
1183 		{0L, NULL, 0L},
1184 		{0L, NULL, 0L},
1185 		{0L, NULL, 0L},
1186 		{0L, NULL, 0L},
1187 		{0L, NULL, 0L},
1188 	    };
1189 
1190 	    size_t pubk_template_len_max = (sizeof(pubktemplate)/sizeof(CK_ATTRIBUTE));
1191 	    size_t pubk_template_len_min = pubk_template_len_max - 12;
1192 	    size_t pubk_num_elems = pubk_template_len_min;
1193 
1194 	    pubkType = CKK_DSA;
1195 	    pubkey_hash_len = get_EVP_PKEY_sha1( pubk, &pubkey_hash);
1196 
1197 	    dsa_prime_len = get_DSA_prime( pubk, &dsa_prime);          /* p */
1198 	    dsa_subprime_len = get_DSA_subprime( pubk, &dsa_subprime); /* q */
1199 	    dsa_base_len = get_DSA_base( pubk, &dsa_base);             /* g */
1200 	    dsa_pubkey_len = get_DSA_pubkey( pubk, &dsa_pubkey);       /* public key */
1201 
1202 	    if( dsa_prime_len > 0 &&
1203 		dsa_subprime_len > 0 &&
1204 		dsa_base_len > 0 &&
1205 		dsa_pubkey_len > 0 ) {
1206 
1207 		/* we have everything, let's fill in the template */
1208 
1209 		pubktemplate[2].pValue = pubkey_hash; /* CKA_ID */
1210 		pubktemplate[2].ulValueLen = pubkey_hash_len;
1211 
1212 		pubktemplate[6].pValue = dsa_prime;
1213 		pubktemplate[6].ulValueLen = dsa_prime_len;
1214 
1215 		pubktemplate[7].pValue = dsa_subprime;
1216 		pubktemplate[7].ulValueLen = dsa_subprime_len;
1217 
1218 		pubktemplate[8].pValue = dsa_base;
1219 		pubktemplate[8].ulValueLen = dsa_base_len;
1220 
1221 		pubktemplate[9].pValue = dsa_pubkey;
1222 		pubktemplate[9].ulValueLen = dsa_pubkey_len;
1223 
1224 		for(i=0; i<numattrs && pubk_num_elems<pubk_template_len_max; i++)
1225 		{
1226 		    switch(attrs[i].type) {
1227 		    case CKA_LABEL:
1228 		    case CKA_ID:
1229 		    case CKA_VERIFY:
1230 		    case CKA_VERIFY_RECOVER: /* not in template onwards */
1231 		    case CKA_DERIVE:
1232 		    case CKA_TRUSTED:
1233 		    case CKA_PRIVATE:
1234 		    case CKA_COPYABLE:
1235 		    case CKA_MODIFIABLE:
1236 		    case CKA_DESTROYABLE:
1237 		    case CKA_START_DATE:
1238 		    case CKA_END_DATE:
1239 		    case CKA_SUBJECT:
1240 		    case CKA_PUBLIC_KEY_INFO:
1241 		    {
1242 			size_t next_pubk_num_elems = pubk_num_elems;
1243 
1244 			CK_ATTRIBUTE_PTR match = lsearch( &attrs[i],
1245 							  pubktemplate,
1246 							  &next_pubk_num_elems,
1247 							  sizeof(CK_ATTRIBUTE),
1248 							  compare_CKA );
1249 
1250 			/* if we have a match and the record was not created by lsearch */
1251 			/* steal the pointer from attrs array. */
1252 			/* It's OK as the template is sitting on the stack, no need */
1253 			/* to dealloc when leaving scope  */
1254 			if(match) {
1255 			    if(next_pubk_num_elems==pubk_num_elems) {
1256 				match->pValue = attrs[i].pValue;           /* copy pointer */
1257 				match->ulValueLen = attrs[i].ulValueLen;   /* adjust length */
1258 			    }
1259 			    else {
1260 				/* everything was copied by lsearch */
1261 				/* just increment array length */
1262 				pubk_num_elems = next_pubk_num_elems;
1263 			    }
1264 			} else {
1265 			    fprintf(stderr, "***Error: can't update attribute array - skipping 0x%08lx\n", attrs[i].type);
1266 			    /* TODO print attribute text */
1267 			}
1268 		    }
1269 		    break;
1270 
1271 		    default:
1272 			if(!is_attribute_skipped(attrs[i].type)) {
1273 			    fprintf(stderr, "***Warning: attribute 0x%08lx skipped\n", attrs[i].type);
1274 			    /* pass */
1275 			}
1276 			break;
1277 		    }
1278 		}
1279 
1280 		retCode = p11Context->FunctionList.C_CreateObject(p11Context->Session,
1281 								  pubktemplate,
1282 								  pubk_num_elems,
1283 								  &pubkhandle);
1284 
1285 		pkcs11_error( retCode, "CreateObject" );
1286 
1287 		/* if we are here, we have to free up memory anyway */
1288 	    }
1289 
1290 	    if(pubkey_hash)  { OPENSSL_free(pubkey_hash); }
1291 	    if(dsa_prime)    { OPENSSL_free(dsa_prime); }
1292 	    if(dsa_subprime) { OPENSSL_free(dsa_subprime); }
1293 	    if(dsa_base)     { OPENSSL_free(dsa_base); }
1294 	    if(dsa_pubkey)   { OPENSSL_free(dsa_pubkey); }
1295 
1296 	}
1297 	    break;
1298 
1299 	case EVP_PKEY_DH: {
1300 	    CK_BYTE_PTR pubkey_hash = NULL;
1301 	    CK_ULONG pubkey_hash_len = 0;
1302 
1303 	    CK_BYTE_PTR dh_prime = NULL;
1304 	    CK_ULONG dh_prime_len = 0;
1305 
1306 	    CK_BYTE_PTR dh_base = NULL;
1307 	    CK_ULONG dh_base_len = 0;
1308 
1309 	    CK_BYTE_PTR dh_pubkey = NULL;
1310 	    CK_ULONG dh_pubkey_len = 0;
1311 
1312 	    CK_ATTRIBUTE pubktemplate[] = {
1313 		{CKA_CLASS, &pubkClass, sizeof pubkClass},           /* 0  */
1314 		{CKA_KEY_TYPE, &pubkType, sizeof pubkType},	     /* 1  */
1315 		{CKA_ID, NULL, 0},				     /* 2  */
1316 		{CKA_LABEL, label, label ? strlen(label) : 0 },	     /* 3  */
1317 		{CKA_DERIVE, source == source_file ? &ck_true : &ck_false, sizeof ck_false }, /* 4  */
1318 		{CKA_TOKEN, &ck_true, sizeof ck_true},		     /* 5  */
1319 		{CKA_PRIME, NULL, 0 },                               /* 6  */
1320 		{CKA_BASE, NULL, 0 },                                /* 7  */
1321 		{CKA_VALUE, NULL, 0 },                               /* 8  */
1322 		/* leave room for up to 12 additional attributes */
1323 		{0L, NULL, 0L},
1324 		{0L, NULL, 0L},
1325 		{0L, NULL, 0L},
1326 		{0L, NULL, 0L},
1327 		{0L, NULL, 0L},
1328 		{0L, NULL, 0L},
1329 		{0L, NULL, 0L},
1330 		{0L, NULL, 0L},
1331 		{0L, NULL, 0L},
1332 		{0L, NULL, 0L},
1333 		{0L, NULL, 0L},
1334 		{0L, NULL, 0L},
1335 	    };
1336 
1337 	    size_t pubk_template_len_max = (sizeof(pubktemplate)/sizeof(CK_ATTRIBUTE));
1338 	    size_t pubk_template_len_min = pubk_template_len_max - 12;
1339 	    size_t pubk_num_elems = pubk_template_len_min;
1340 
1341 	    pubkType = CKK_DH;
1342 	    pubkey_hash_len = get_EVP_PKEY_sha1( pubk, &pubkey_hash);
1343 
1344 	    dh_prime_len = get_DH_prime( pubk, &dh_prime);          /* p */
1345 	    dh_base_len = get_DH_base( pubk, &dh_base);             /* g */
1346 	    dh_pubkey_len = get_DH_pubkey( pubk, &dh_pubkey);       /* public key */
1347 
1348 	    if( dh_prime_len > 0 &&
1349 		dh_base_len > 0 &&
1350 		dh_pubkey_len > 0 ) {
1351 
1352 		/* we have everything, let's fill in the template */
1353 
1354 		pubktemplate[2].pValue = pubkey_hash; /* CKA_ID */
1355 		pubktemplate[2].ulValueLen = pubkey_hash_len;
1356 
1357 		pubktemplate[6].pValue = dh_prime;
1358 		pubktemplate[6].ulValueLen = dh_prime_len;
1359 
1360 		pubktemplate[7].pValue = dh_base;
1361 		pubktemplate[7].ulValueLen = dh_base_len;
1362 
1363 		pubktemplate[8].pValue = dh_pubkey;
1364 		pubktemplate[8].ulValueLen = dh_pubkey_len;
1365 
1366 		for(i=0; i<numattrs && pubk_num_elems<pubk_template_len_max; i++)
1367 		{
1368 		    switch(attrs[i].type) {
1369 		    case CKA_LABEL:
1370 		    case CKA_ID:
1371 		    case CKA_DERIVE:
1372 		    case CKA_TRUSTED: /* not in template onwards */
1373 		    case CKA_PRIVATE:
1374 		    case CKA_COPYABLE:
1375 		    case CKA_MODIFIABLE:
1376 		    case CKA_DESTROYABLE:
1377 		    case CKA_START_DATE:
1378 		    case CKA_END_DATE:
1379 		    case CKA_SUBJECT:
1380 		    case CKA_PUBLIC_KEY_INFO:
1381 		    {
1382 			size_t next_pubk_num_elems = pubk_num_elems;
1383 
1384 			CK_ATTRIBUTE_PTR match = lsearch( &attrs[i],
1385 							  pubktemplate,
1386 							  &next_pubk_num_elems,
1387 							  sizeof(CK_ATTRIBUTE),
1388 							  compare_CKA );
1389 
1390 			/* if we have a match and the record was not created by lsearch */
1391 			/* steal the pointer from attrs array. */
1392 			/* It's OK as the template is sitting on the stack, no need */
1393 			/* to dealloc when leaving scope  */
1394 			if(match) {
1395 			    if(next_pubk_num_elems==pubk_num_elems) {
1396 				match->pValue = attrs[i].pValue;           /* copy pointer */
1397 				match->ulValueLen = attrs[i].ulValueLen;   /* adjust length */
1398 			    }
1399 			    else {
1400 				/* everything was copied by lsearch */
1401 				/* just increment array length */
1402 				pubk_num_elems = next_pubk_num_elems;
1403 			    }
1404 			} else {
1405 			    fprintf(stderr, "***Error: can't update attribute array - skipping 0x%08lx\n", attrs[i].type);
1406 			    /* TODO print attribute text */
1407 			}
1408 		    }
1409 		    break;
1410 
1411 		    default:
1412 			if(!is_attribute_skipped(attrs[i].type)) {
1413 			    fprintf(stderr, "***Warning: attribute 0x%08lx skipped\n", attrs[i].type);
1414 			    /* pass */
1415 			}
1416 			break;
1417 		    }
1418 		}
1419 
1420 		retCode = p11Context->FunctionList.C_CreateObject(p11Context->Session,
1421 								  pubktemplate,
1422 								  pubk_num_elems,
1423 								  &pubkhandle);
1424 
1425 		pkcs11_error( retCode, "CreateObject" );
1426 
1427 		/* if we are here, we have to free up memory anyway */
1428 	    }
1429 
1430 	    if(pubkey_hash)  { OPENSSL_free(pubkey_hash); }
1431 	    if(dh_prime)    { OPENSSL_free(dh_prime); }
1432 	    if(dh_base)     { OPENSSL_free(dh_base); }
1433 	    if(dh_pubkey)   { OPENSSL_free(dh_pubkey); }
1434 	}
1435 	    break;
1436 
1437 	case EVP_PKEY_ED25519:
1438 	case EVP_PKEY_ED448: {
1439 	    CK_BYTE_PTR pubkey_hash = NULL;
1440 	    CK_ULONG pubkey_hash_len = 0;
1441 
1442 	    CK_BYTE_PTR ec_params = NULL;
1443 	    CK_ULONG ec_params_len = 0;
1444 
1445 	    CK_BYTE_PTR ec_point = NULL;
1446 	    CK_ULONG ec_point_len = 0;
1447 
1448 	    CK_ATTRIBUTE pubktemplate[] = {
1449 		{CKA_CLASS, &pubkClass, sizeof pubkClass },          /* 0  */
1450 		{CKA_KEY_TYPE, &pubkType, sizeof pubkType},	     /* 1  */
1451 		{CKA_ID, NULL, 0},				     /* 2  */
1452 		{CKA_LABEL, label, label ? strlen(label) : 0 },	     /* 3  */
1453 		{CKA_VERIFY, source == source_file ? &ck_true : &ck_false, sizeof ck_false }, /* 4  */
1454 		{CKA_TOKEN, &ck_true, sizeof ck_true},		     /* 5  */
1455 		{CKA_EC_PARAMS, NULL, 0 },                           /* 6  */
1456 		{CKA_EC_POINT, NULL, 0 },                            /* 7  */
1457 		/* leave room for up to 12 additional attributes */
1458 		{0L, NULL, 0L},
1459 		{0L, NULL, 0L},
1460 		{0L, NULL, 0L},
1461 		{0L, NULL, 0L},
1462 		{0L, NULL, 0L},
1463 		{0L, NULL, 0L},
1464 		{0L, NULL, 0L},
1465 		{0L, NULL, 0L},
1466 		{0L, NULL, 0L},
1467 		{0L, NULL, 0L},
1468 		{0L, NULL, 0L},
1469 		{0L, NULL, 0L},
1470 	    };
1471 
1472 	    size_t pubk_template_len_max = (sizeof(pubktemplate)/sizeof(CK_ATTRIBUTE));
1473 	    size_t pubk_template_len_min = pubk_template_len_max - 12;
1474 	    size_t pubk_num_elems = pubk_template_len_min;
1475 
1476 	    pubkType = CKK_EC_EDWARDS;
1477 	    pubkey_hash_len = get_EVP_PKEY_sha1( pubk, &pubkey_hash);
1478 
1479 	    ec_params_len = get_ED_params( pubk, &ec_params);           /* curve parameters */
1480 	    ec_point_len  = get_ED_point( pubk, &ec_point);             /* curve point */
1481 
1482 	    if( ec_params_len > 0 && ec_point_len > 0 ) {
1483 
1484 		/* we have everything, let's fill in the template */
1485 
1486 		pubktemplate[2].pValue = pubkey_hash; /* CKA_ID */
1487 		pubktemplate[2].ulValueLen = pubkey_hash_len;
1488 
1489 		pubktemplate[6].pValue = ec_params;
1490 		pubktemplate[6].ulValueLen = ec_params_len;
1491 
1492 		pubktemplate[7].pValue = ec_point;
1493 		pubktemplate[7].ulValueLen = ec_point_len;
1494 
1495 		for(i=0; i<numattrs && pubk_num_elems<pubk_template_len_max; i++)
1496 		{
1497 		    switch(attrs[i].type) {
1498 		    case CKA_LABEL:
1499 		    case CKA_ID:
1500 		    case CKA_VERIFY:
1501 		    case CKA_VERIFY_RECOVER: /* not in template onwards */
1502 		    case CKA_DERIVE:
1503 		    case CKA_TRUSTED:
1504 		    case CKA_PRIVATE:
1505 		    case CKA_COPYABLE:
1506 		    case CKA_MODIFIABLE:
1507 		    case CKA_DESTROYABLE:
1508 		    case CKA_START_DATE:
1509 		    case CKA_END_DATE:
1510 		    case CKA_SUBJECT:
1511 		    case CKA_PUBLIC_KEY_INFO:
1512 		    {
1513 			size_t next_pubk_num_elems = pubk_num_elems;
1514 
1515 			CK_ATTRIBUTE_PTR match = lsearch( &attrs[i],
1516 							  pubktemplate,
1517 							  &next_pubk_num_elems,
1518 							  sizeof(CK_ATTRIBUTE),
1519 							  compare_CKA );
1520 
1521 			/* if we have a match and the record was not created by lsearch */
1522 			/* steal the pointer from attrs array. */
1523 			/* It's OK as the template is sitting on the stack, no need */
1524 			/* to dealloc when leaving scope  */
1525 			if(match) {
1526 			    if(next_pubk_num_elems==pubk_num_elems) {
1527 				match->pValue = attrs[i].pValue;           /* copy pointer */
1528 				match->ulValueLen = attrs[i].ulValueLen;   /* adjust length */
1529 			    }
1530 			    else {
1531 				/* everything was copied by lsearch */
1532 				/* just increment array length */
1533 				pubk_num_elems = next_pubk_num_elems;
1534 			    }
1535 			} else {
1536 			    fprintf(stderr, "***Error: can't update attribute array - skipping 0x%08lx\n", attrs[i].type);
1537 			    /* TODO print attribute text */
1538 			}
1539 		    }
1540 		    break;
1541 
1542 		    default:
1543 			if(!is_attribute_skipped(attrs[i].type)) {
1544 			    fprintf(stderr, "***Warning: attribute 0x%08lx skipped\n", attrs[i].type);
1545 			    /* pass */
1546 			}
1547 			break;
1548 		    }
1549 		}
1550 
1551 		retCode = p11Context->FunctionList.C_CreateObject(p11Context->Session,
1552 								  pubktemplate,
1553 								  pubk_num_elems,
1554 								  &pubkhandle);
1555 
1556 		if(retCode != CKR_OK) {
1557 		    pkcs11_error( retCode, "CreateObject" );
1558 		}
1559 
1560 		/* if we are here, we have to free up memory anyway */
1561 	    }
1562 
1563 	    if(pubkey_hash)  { OPENSSL_free(pubkey_hash); }
1564 	    if(ec_params)    { OPENSSL_free(ec_params); }
1565 	    if(ec_point)     { OPENSSL_free(ec_point); }
1566 	}
1567 	    break;
1568 
1569 	case EVP_PKEY_EC: {
1570 	    CK_BYTE_PTR pubkey_hash = NULL;
1571 	    CK_ULONG pubkey_hash_len = 0;
1572 
1573 	    CK_BYTE_PTR ec_params = NULL;
1574 	    CK_ULONG ec_params_len = 0;
1575 
1576 	    CK_BYTE_PTR ec_point = NULL;
1577 	    CK_ULONG ec_point_len = 0;
1578 
1579 	    CK_ATTRIBUTE pubktemplate[] = {
1580 		{CKA_CLASS, &pubkClass, sizeof pubkClass },          /* 0  */
1581 		{CKA_KEY_TYPE, &pubkType, sizeof pubkType},	     /* 1  */
1582 		{CKA_ID, NULL, 0},				     /* 2  */
1583 		{CKA_LABEL, label, label ? strlen(label) : 0 },	     /* 3  */
1584 		{CKA_VERIFY, source == source_file ? &ck_true : &ck_false, sizeof ck_false}, /* 4  */
1585 		{CKA_TOKEN, &ck_true, sizeof ck_true},		     /* 5  */
1586 		{CKA_EC_PARAMS, NULL, 0 },                           /* 6  */
1587 		{CKA_EC_POINT, NULL, 0 },                            /* 7  */
1588 		/* leave room for up to 12 additional attributes */
1589 		{0L, NULL, 0L},
1590 		{0L, NULL, 0L},
1591 		{0L, NULL, 0L},
1592 		{0L, NULL, 0L},
1593 		{0L, NULL, 0L},
1594 		{0L, NULL, 0L},
1595 		{0L, NULL, 0L},
1596 		{0L, NULL, 0L},
1597 		{0L, NULL, 0L},
1598 		{0L, NULL, 0L},
1599 		{0L, NULL, 0L},
1600 		{0L, NULL, 0L},
1601 	    };
1602 
1603 	    size_t pubk_template_len_max = (sizeof(pubktemplate)/sizeof(CK_ATTRIBUTE));
1604 	    size_t pubk_template_len_min = pubk_template_len_max - 12;
1605 	    size_t pubk_num_elems = pubk_template_len_min;
1606 
1607 	    pubkType = CKK_EC;
1608 	    pubkey_hash_len = get_EVP_PKEY_sha1( pubk, &pubkey_hash);
1609 
1610 	    ec_params_len = get_EC_params( pubk, &ec_params);           /* curve parameters */
1611 	    ec_point_len  = get_EC_point( pubk, &ec_point);             /* curve point */
1612 
1613 	    if( ec_params_len > 0 &&
1614 		ec_point_len > 0 ) {
1615 
1616 		/* we have everything, let's fill in the template */
1617 
1618 		pubktemplate[2].pValue = pubkey_hash; /* CKA_ID */
1619 		pubktemplate[2].ulValueLen = pubkey_hash_len;
1620 
1621 		pubktemplate[6].pValue = ec_params;
1622 		pubktemplate[6].ulValueLen = ec_params_len;
1623 
1624 		pubktemplate[7].pValue = ec_point;
1625 		pubktemplate[7].ulValueLen = ec_point_len;
1626 
1627 		for(i=0; i<numattrs && pubk_num_elems<pubk_template_len_max; i++)
1628 		{
1629 		    switch(attrs[i].type) {
1630 		    case CKA_LABEL:
1631 		    case CKA_ID:
1632 		    case CKA_WRAP:
1633 		    case CKA_VERIFY:
1634 		    case CKA_VERIFY_RECOVER: /* not in template onwards */
1635 		    case CKA_DERIVE:
1636 		    case CKA_TRUSTED:
1637 		    case CKA_PRIVATE:
1638 		    case CKA_WRAP_TEMPLATE:
1639 		    case CKA_COPYABLE:
1640 		    case CKA_MODIFIABLE:
1641 		    case CKA_DESTROYABLE:
1642 		    case CKA_START_DATE:
1643 		    case CKA_END_DATE:
1644 		    case CKA_SUBJECT:
1645 		    case CKA_PUBLIC_KEY_INFO:
1646 		    {
1647 			size_t next_pubk_num_elems = pubk_num_elems;
1648 
1649 			CK_ATTRIBUTE_PTR match = lsearch( &attrs[i],
1650 							  pubktemplate,
1651 							  &next_pubk_num_elems,
1652 							  sizeof(CK_ATTRIBUTE),
1653 							  compare_CKA );
1654 
1655 			/* if we have a match and the record was not created by lsearch */
1656 			/* steal the pointer from attrs array. */
1657 			/* It's OK as the template is sitting on the stack, no need */
1658 			/* to dealloc when leaving scope  */
1659 			if(match) {
1660 			    if(next_pubk_num_elems==pubk_num_elems) {
1661 				match->pValue = attrs[i].pValue;           /* copy pointer */
1662 				match->ulValueLen = attrs[i].ulValueLen;   /* adjust length */
1663 			    }
1664 			    else {
1665 				/* everything was copied by lsearch */
1666 				/* just increment array length */
1667 				pubk_num_elems = next_pubk_num_elems;
1668 			    }
1669 			} else {
1670 			    fprintf(stderr, "***Error: can't update attribute array - skipping 0x%08lx\n", attrs[i].type);
1671 			    /* TODO print attribute text */
1672 			}
1673 		    }
1674 		    break;
1675 
1676 		    default:
1677 			if(!is_attribute_skipped(attrs[i].type)) {
1678 			    fprintf(stderr, "***Warning: attribute 0x%08lx skipped\n", attrs[i].type);
1679 			    /* pass */
1680 			}
1681 			break;
1682 		    }
1683 		}
1684 
1685 		retCode = p11Context->FunctionList.C_CreateObject(p11Context->Session,
1686 								  pubktemplate,
1687 								  pubk_num_elems,
1688 								  &pubkhandle);
1689 
1690 		if(retCode != CKR_OK) {
1691 		    pkcs11_error( retCode, "CreateObject" );
1692 		}
1693 
1694 		/* if we are here, we have to free up memory anyway */
1695 	    }
1696 
1697 	    if(pubkey_hash)  { OPENSSL_free(pubkey_hash); }
1698 	    if(ec_params)    { OPENSSL_free(ec_params); }
1699 	    if(ec_point)     { OPENSSL_free(ec_point); }
1700 	}
1701 	    break;
1702 
1703 	default:
1704 	    fprintf(stderr, "***ERROR - public key type not supported\n");
1705 	    break;
1706 	}
1707 
1708 	OPENSSL_free(pubk);
1709 
1710     }
1711     return pubkhandle;
1712 }
1713 
1714 /* public interface */
1715 
pkcs11_new_SKI_value_from_pubk(EVP_PKEY * pubkey,CK_BYTE_PTR * buf)1716 inline CK_ULONG pkcs11_new_SKI_value_from_pubk(EVP_PKEY *pubkey, CK_BYTE_PTR *buf) {
1717     return get_EVP_PKEY_sha1(pubkey, buf);
1718 }
1719 
1720 
pkcs11_importpubk(pkcs11Context * p11Context,char * filename,char * label,CK_ATTRIBUTE attrs[],CK_ULONG numattrs)1721 inline CK_OBJECT_HANDLE pkcs11_importpubk( pkcs11Context * p11Context,
1722 					   char *filename,
1723 					   char *label,
1724 					   CK_ATTRIBUTE attrs[],
1725 					   CK_ULONG numattrs ) {
1726     return _importpubk(p11Context, filename, NULL, 0, label, attrs, numattrs, source_file);
1727 }
1728 
pkcs11_importpubk_from_buffer(pkcs11Context * p11Context,unsigned char * buffer,size_t len,char * label,CK_ATTRIBUTE attrs[],CK_ULONG numattrs)1729 inline CK_OBJECT_HANDLE pkcs11_importpubk_from_buffer( pkcs11Context * p11Context,
1730 						       unsigned char *buffer,
1731 						       size_t len,
1732 						       char *label,
1733 						       CK_ATTRIBUTE attrs[],
1734 						       CK_ULONG numattrs ) {
1735     return _importpubk(p11Context, NULL, buffer, len, label, attrs, numattrs, source_buffer);
1736 }
1737 
1738