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