Fix safestack issues in x509.h
[openssl.git] / test / pkcs12_helper.c
1 /*
2  * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9
10 #include <stdio.h>
11 #include <string.h>
12 #include <stdlib.h>
13
14 #include "internal/nelem.h"
15
16 #include <openssl/pkcs12.h>
17 #include <openssl/x509.h>
18 #include <openssl/x509v3.h>
19 #include <openssl/pem.h>
20
21 #include "testutil.h"
22 #include "pkcs12_helper.h"
23
24 DEFINE_STACK_OF(PKCS7)
25 DEFINE_STACK_OF(PKCS12_SAFEBAG)
26
27 /* Set this to > 0 write test data to file */
28 int write_files = 0;
29
30 /* -------------------------------------------------------------------------
31  * Local function declarations
32  */
33
34 static X509 *load_cert(const unsigned char *bytes, int len);
35 static EVP_PKEY *load_pkey(const unsigned char *bytes, int len);
36
37 static int add_attributes(PKCS12_SAFEBAG *bag, const PKCS12_ATTR *attrs);
38
39 static void generate_p12(PKCS12_BUILDER *pb, const PKCS12_ENC *mac);
40 static int write_p12(PKCS12 *p12, const char *outfile);
41
42 static PKCS12 *from_bio_p12(BIO *bio, const PKCS12_ENC *mac);
43 static PKCS12 *read_p12(const char *infile, const PKCS12_ENC *mac);
44 static int check_p12_mac(PKCS12 *p12, const PKCS12_ENC *mac);
45 static int check_asn1_string(const ASN1_TYPE *av, const char *txt);
46 static int check_attrs(const STACK_OF(X509_ATTRIBUTE) *bag_attrs, const PKCS12_ATTR *attrs);
47
48
49 /* --------------------------------------------------------------------------
50  * Test data load functions
51  */
52
53 static X509 *load_cert(const unsigned char *bytes, int len)
54 {
55     X509 *cert = NULL;
56
57     cert = d2i_X509(NULL, &bytes, len);
58     if (!TEST_ptr(cert))
59         goto err;
60 err:
61     return cert;
62 }
63
64 static EVP_PKEY *load_pkey(const unsigned char *bytes, int len)
65 {
66     EVP_PKEY *pkey = NULL;
67
68     pkey = d2i_AutoPrivateKey(NULL, &bytes, len);
69     if (!TEST_ptr(pkey))
70         goto err;
71 err:
72     return pkey;
73 }
74
75
76 /* -------------------------------------------------------------------------
77  * PKCS12 builder
78  */
79
80 PKCS12_BUILDER *new_pkcs12_builder(const char *filename)
81 {
82     PKCS12_BUILDER *pb = OPENSSL_malloc(sizeof(PKCS12_BUILDER));
83     if (!TEST_ptr(pb))
84         return NULL;
85
86     pb->filename = filename;
87     pb->success = 1;
88     return pb;
89 }
90
91 int end_pkcs12_builder(PKCS12_BUILDER *pb)
92 {
93     int result = pb->success;
94
95     OPENSSL_free(pb);
96     return result;
97 }
98
99
100 void start_pkcs12(PKCS12_BUILDER *pb)
101 {
102     pb->safes = NULL;
103 }
104
105
106 void end_pkcs12(PKCS12_BUILDER *pb)
107 {
108     if (!pb->success)
109         return;
110     generate_p12(pb, NULL);
111 }
112
113
114 void end_pkcs12_with_mac(PKCS12_BUILDER *pb, const PKCS12_ENC *mac)
115 {
116     if (!pb->success)
117         return;
118     generate_p12(pb, mac);
119 }
120
121
122 /* Generate the PKCS12 encoding and write to memory bio */
123 static void generate_p12(PKCS12_BUILDER *pb, const PKCS12_ENC *mac)
124 {
125     PKCS12 *p12;
126
127     if (!pb->success)
128         return;
129
130     pb->p12bio = BIO_new(BIO_s_mem());
131     if (!TEST_ptr(pb->p12bio)) {
132         pb->success = 0;
133         return;
134     }
135     p12 = PKCS12_add_safes(pb->safes, 0);
136     if (!TEST_ptr(p12)) {
137         pb->success = 0;
138         goto err;
139     }
140     sk_PKCS7_pop_free(pb->safes, PKCS7_free);
141
142     if (mac != NULL) {
143         if (!TEST_true(PKCS12_set_mac(p12, mac->pass, strlen(mac->pass),
144                                       NULL, 0, mac->iter, EVP_get_digestbynid(mac->nid)))) {
145             pb->success = 0;
146             goto err;
147         }
148     }
149     i2d_PKCS12_bio(pb->p12bio, p12);
150
151     /* Can write to file here for debug */
152     if (write_files)
153         write_p12(p12, pb->filename);
154 err:
155     PKCS12_free(p12);
156 }
157
158
159 static int write_p12(PKCS12 *p12, const char *outfile)
160 {
161     int ret = 0;
162     BIO *out = BIO_new_file(outfile, "w");
163
164     if (out == NULL)
165         goto err;
166
167     if (!TEST_int_eq(i2d_PKCS12_bio(out, p12), 1))
168         goto err;
169     ret = 1;
170 err:
171     BIO_free(out);
172     return ret;
173 }
174
175 static PKCS12 *from_bio_p12(BIO *bio, const PKCS12_ENC *mac)
176 {
177     PKCS12 *p12 = NULL;
178
179     p12 = d2i_PKCS12_bio(bio, NULL);
180     BIO_free(bio);
181     if (!TEST_ptr(p12))
182         goto err;
183     if (mac == NULL) {
184         if (!TEST_false(PKCS12_mac_present(p12)))
185             goto err;
186     } else {
187         if (!check_p12_mac(p12, mac))
188             goto err;
189     }
190     return p12;
191 err:
192     PKCS12_free(p12);
193     return NULL;
194 }
195
196
197 /* For use with existing files */
198 static PKCS12 *read_p12(const char *infile, const PKCS12_ENC *mac)
199 {
200     PKCS12 *p12 = NULL;
201     BIO *in = BIO_new_file(infile, "r");
202
203     if (in == NULL)
204         goto err;
205     p12 = d2i_PKCS12_bio(in, NULL);
206     BIO_free(in);
207     if (!TEST_ptr(p12))
208         goto err;
209     if (mac == NULL) {
210         if (!TEST_false(PKCS12_mac_present(p12)))
211             goto err;
212     } else {
213         if (!check_p12_mac(p12, mac))
214             goto err;
215     }
216     return p12;
217 err:
218     PKCS12_free(p12);
219     return NULL;
220 }
221
222 static int check_p12_mac(PKCS12 *p12, const PKCS12_ENC *mac)
223 {
224     return TEST_true(PKCS12_mac_present(p12))
225         && TEST_true(PKCS12_verify_mac(p12, mac->pass, strlen(mac->pass)));
226 }
227
228
229 /* -------------------------------------------------------------------------
230  * PKCS7 content info builder
231  */
232
233 void start_contentinfo(PKCS12_BUILDER *pb)
234 {
235     pb->bags = NULL;
236 }
237
238
239 void end_contentinfo(PKCS12_BUILDER *pb)
240 {
241     if (pb->success) {
242         if (pb->bags && !TEST_true(PKCS12_add_safe(&pb->safes, pb->bags, -1, 0, NULL))) {
243             pb->success = 0;
244             return;
245         }
246     }
247     sk_PKCS12_SAFEBAG_pop_free(pb->bags, PKCS12_SAFEBAG_free);
248     pb->bags = NULL;
249 }
250
251
252 void end_contentinfo_encrypted(PKCS12_BUILDER *pb, const PKCS12_ENC *enc)
253 {
254     if (pb->success) {
255         if (pb->bags 
256             && !TEST_true(PKCS12_add_safe(&pb->safes, pb->bags, enc->nid, enc->iter, enc->pass))) {
257             pb->success = 0;
258             return;
259         }
260     }
261     sk_PKCS12_SAFEBAG_pop_free(pb->bags, PKCS12_SAFEBAG_free);
262     pb->bags = NULL;
263 }
264
265
266 static STACK_OF(PKCS12_SAFEBAG) *decode_contentinfo(STACK_OF(PKCS7) *safes, int idx, const PKCS12_ENC *enc)
267 {
268     STACK_OF(PKCS12_SAFEBAG) *bags = NULL;
269     PKCS7 *p7 = sk_PKCS7_value(safes, idx);
270     int bagnid = OBJ_obj2nid(p7->type);
271
272     if (enc) {
273         if (!TEST_int_eq(bagnid, NID_pkcs7_encrypted))
274             goto err;
275         /* TODO: Check algorithm (iterations?) against what we originally set */
276         bags = PKCS12_unpack_p7encdata(p7, enc->pass, strlen(enc->pass));
277     } else {
278         if (!TEST_int_eq(bagnid, NID_pkcs7_data))
279             goto err;
280         bags = PKCS12_unpack_p7data(p7);
281     }
282     if (!TEST_ptr(bags))
283         goto err;
284
285     return bags;
286 err:
287     return NULL;
288 }
289
290
291 /* -------------------------------------------------------------------------
292  * PKCS12 safeBag/attribute builder
293  */
294
295 static int add_attributes(PKCS12_SAFEBAG *bag, const PKCS12_ATTR *attrs)
296 {
297     int ret = 0;
298     int attr_nid;
299     const PKCS12_ATTR *p_attr = attrs;
300
301     if (attrs == NULL)
302         return 1;
303
304     while (p_attr->oid != NULL) {
305         TEST_info("Adding attribute %s = %s", p_attr->oid, p_attr->value);
306         attr_nid = OBJ_txt2nid(p_attr->oid);
307
308         if (attr_nid == NID_friendlyName) {
309             if (!TEST_true(PKCS12_add_friendlyname(bag, p_attr->value, -1)))
310                 goto err;
311         } else if (attr_nid == NID_localKeyID) {
312             if (!TEST_true(PKCS12_add_localkeyid(bag, (unsigned char *)p_attr->value,
313                                                  strlen(p_attr->value))))
314                 goto err;
315         } else {
316             /* Custom attribute values limited to ASCII in these tests */
317             if (!TEST_true(PKCS12_add1_attr_by_txt(bag, p_attr->oid, MBSTRING_ASC,
318                                                    (unsigned char *)p_attr->value,
319                                                    strlen(p_attr->value))))
320                 goto err;
321         }
322         p_attr++;
323     }
324     ret = 1;
325 err:
326     return ret;
327 }
328
329 void add_certbag(PKCS12_BUILDER *pb, const unsigned char *bytes, int len,
330                  const PKCS12_ATTR *attrs)
331 {
332     PKCS12_SAFEBAG *bag = NULL;
333     X509 *cert = NULL;
334     char *name;
335
336     if (!pb->success)
337         return;
338
339     cert = load_cert(bytes, len);
340     if (!TEST_ptr(cert)) {
341         pb->success = 0;
342         return;
343     }
344
345     name = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0);
346     TEST_info("Adding certificate <%s>", name);
347     OPENSSL_free(name);
348
349     bag = PKCS12_add_cert(&pb->bags, cert);
350     if (!TEST_ptr(bag)) {
351         pb->success = 0;
352         goto err;
353     }
354
355     if (!TEST_true(add_attributes(bag, attrs))) {
356         pb->success = 0;
357         goto err;
358     }
359 err:
360     X509_free(cert);
361 }
362
363 void add_keybag(PKCS12_BUILDER *pb, const unsigned char *bytes, int len,
364                 const PKCS12_ATTR *attrs, const PKCS12_ENC *enc)
365 {
366     PKCS12_SAFEBAG *bag = NULL;
367     EVP_PKEY *pkey = NULL;
368
369     if (!pb->success)
370         return;
371
372     TEST_info("Adding key");
373
374     pkey = load_pkey(bytes, len);
375     if (!TEST_ptr(pkey)) {
376         pb->success = 0;
377         return;
378     }
379
380     bag = PKCS12_add_key(&pb->bags, pkey, 0 /*keytype*/, enc->iter, enc->nid, enc->pass);
381     if (!TEST_ptr(bag)) {
382         pb->success = 0;
383         goto err;
384     }
385     if (!add_attributes(bag, attrs))
386         pb->success = 0;
387 err:
388     EVP_PKEY_free(pkey);
389 }
390
391 void add_secretbag(PKCS12_BUILDER *pb, int secret_nid, const char *secret,
392                                const PKCS12_ATTR *attrs)
393 {
394     PKCS12_SAFEBAG *bag = NULL;
395
396     if (!pb->success)
397         return;
398
399     TEST_info("Adding secret <%s>", secret);
400
401     bag = PKCS12_add_secret(&pb->bags, secret_nid, (const unsigned char *)secret, strlen(secret));
402     if (!TEST_ptr(bag)) {
403         pb->success = 0;
404         return;
405     }
406     if (!add_attributes(bag, attrs))
407         pb->success = 0;
408 }
409
410
411 /* -------------------------------------------------------------------------
412  * PKCS12 structure checking
413  */
414
415 static int check_asn1_string(const ASN1_TYPE *av, const char *txt)
416 {
417     int ret = 0;
418     char *value = NULL;
419
420     if (!TEST_ptr(av))
421         goto err;
422
423     switch (av->type) {
424     case V_ASN1_BMPSTRING:
425         value = OPENSSL_uni2asc(av->value.bmpstring->data,
426                                 av->value.bmpstring->length);
427         if (!TEST_str_eq(txt, (char *)value))
428             goto err;
429         break;
430
431     case V_ASN1_UTF8STRING:
432         if (!TEST_str_eq(txt, (char *)av->value.utf8string->data))
433             goto err;
434         break;
435
436     case V_ASN1_OCTET_STRING:
437         if (!TEST_str_eq(txt, (char *)av->value.octet_string->data))
438             goto err;
439         break;
440
441     default:
442         /* Tests do not support other attribute types currently */
443         goto err;
444     }
445     ret = 1;
446 err:
447     OPENSSL_free(value);
448     return ret;
449 }
450
451 static int check_attrs(const STACK_OF(X509_ATTRIBUTE) *bag_attrs, const PKCS12_ATTR *attrs)
452 {
453     int ret = 0;
454     X509_ATTRIBUTE *attr;
455     ASN1_TYPE *av;
456     int i, j;
457     char attr_txt[100];
458
459     for (i = 0; i < sk_X509_ATTRIBUTE_num(bag_attrs); i++) {
460         const PKCS12_ATTR *p_attr = attrs;
461         ASN1_OBJECT *attr_obj;
462
463         attr = sk_X509_ATTRIBUTE_value(bag_attrs, i);
464         attr_obj = X509_ATTRIBUTE_get0_object(attr);
465         OBJ_obj2txt(attr_txt, 100, attr_obj, 0);
466
467         while(p_attr->oid != NULL) {
468             /* Find a matching attribute type */
469             if (strcmp(p_attr->oid, attr_txt) == 0) {
470
471                 /* TODO: Handle multi-value attributes */
472                 if (!TEST_int_eq(X509_ATTRIBUTE_count(attr), 1))
473                     goto err;
474
475                 for (j = 0; j < X509_ATTRIBUTE_count(attr); j++)
476                 {
477                     av = X509_ATTRIBUTE_get0_type(attr, j);
478                     if (!TEST_true(check_asn1_string(av, p_attr->value)))
479                         goto err;
480                 }
481                 break;
482             }
483             p_attr++;
484         }
485     }
486     ret = 1;
487 err:
488     return ret;
489 }
490
491 void check_certbag(PKCS12_BUILDER *pb, const unsigned char *bytes, int len,
492                    const PKCS12_ATTR *attrs)
493 {
494     X509 *x509 = NULL;
495     X509 *ref_x509 = NULL;
496     const PKCS12_SAFEBAG *bag;
497
498     if (!pb->success)
499         return;
500
501     bag = sk_PKCS12_SAFEBAG_value(pb->bags, pb->bag_idx++);
502     if (!TEST_ptr(bag)) {
503         pb->success = 0;
504         return;
505     }
506     if (!check_attrs(PKCS12_SAFEBAG_get0_attrs(bag), attrs)
507         || !TEST_int_eq(PKCS12_SAFEBAG_get_nid(bag), NID_certBag)
508         || !TEST_int_eq(PKCS12_SAFEBAG_get_bag_nid(bag), NID_x509Certificate)) {
509         pb->success = 0;
510         return;
511     }
512     x509 = PKCS12_SAFEBAG_get1_cert(bag);
513     if (!TEST_ptr(x509)) {
514         pb->success = 0;
515         goto err;
516     }
517     ref_x509 = load_cert(bytes, len);
518     if (!TEST_false(X509_cmp(x509, ref_x509)))
519         pb->success = 0;
520 err:
521     X509_free(x509);
522     X509_free(ref_x509);
523 }
524
525 void check_keybag(PKCS12_BUILDER *pb, const unsigned char *bytes, int len,
526                   const PKCS12_ATTR *attrs, const PKCS12_ENC *enc)
527 {
528     EVP_PKEY *pkey = NULL;
529     EVP_PKEY *ref_pkey = NULL;
530     PKCS8_PRIV_KEY_INFO *p8;
531     const PKCS8_PRIV_KEY_INFO *p8c;
532     const PKCS12_SAFEBAG *bag;
533
534     if (!pb->success)
535         return;
536
537     bag = sk_PKCS12_SAFEBAG_value(pb->bags, pb->bag_idx++);
538     if (!TEST_ptr(bag)) {
539         pb->success = 0;
540         return;
541     }
542
543     if (!check_attrs(PKCS12_SAFEBAG_get0_attrs(bag), attrs)) {
544         pb->success = 0;
545         return;
546     }
547
548     switch (PKCS12_SAFEBAG_get_nid(bag)) {
549     case NID_keyBag:
550         p8c = PKCS12_SAFEBAG_get0_p8inf(bag);
551         if (!TEST_ptr(pkey = EVP_PKCS82PKEY(p8c))) {
552             pb->success = 0;
553             goto err;
554         }
555         /* TODO: handle key attributes */
556         /* PKCS8_pkey_get0_attrs(p8c); */
557         break;
558
559     case NID_pkcs8ShroudedKeyBag:
560         if (!TEST_ptr(p8 = PKCS12_decrypt_skey(bag, enc->pass, strlen(enc->pass)))) {
561             pb->success = 0;
562             goto err;
563         }
564         if (!TEST_ptr(pkey = EVP_PKCS82PKEY(p8))) {
565             PKCS8_PRIV_KEY_INFO_free(p8);
566             pb->success = 0;
567             goto err;
568         }
569         /* TODO: handle key attributes */
570         /* PKCS8_pkey_get0_attrs(p8); */
571         PKCS8_PRIV_KEY_INFO_free(p8);
572         break;
573
574     default:
575         pb->success = 0;
576         goto err;
577     }
578
579     /* PKEY compare returns 1 for match */
580     ref_pkey = load_pkey(bytes, len);
581     if (!TEST_true(EVP_PKEY_eq(pkey, ref_pkey)))
582         pb->success = 0;
583 err:
584     EVP_PKEY_free(pkey);
585     EVP_PKEY_free(ref_pkey);
586 }
587
588 void check_secretbag(PKCS12_BUILDER *pb, int secret_nid, const char *secret, const PKCS12_ATTR *attrs)
589 {
590     const PKCS12_SAFEBAG *bag;
591
592     if (!pb->success)
593         return;
594         
595     bag = sk_PKCS12_SAFEBAG_value(pb->bags, pb->bag_idx++);
596     if (!TEST_ptr(bag)) {
597         pb->success = 0;
598         return;
599     }   
600     
601     if (!check_attrs(PKCS12_SAFEBAG_get0_attrs(bag), attrs)
602         || !TEST_int_eq(PKCS12_SAFEBAG_get_nid(bag), NID_secretBag)
603         || !TEST_int_eq(PKCS12_SAFEBAG_get_bag_nid(bag), secret_nid)
604         || !TEST_true(check_asn1_string(PKCS12_SAFEBAG_get0_bag_obj(bag), secret)))
605         pb->success = 0;
606 }
607
608
609 void start_check_pkcs12(PKCS12_BUILDER *pb)
610 {
611     PKCS12 *p12 = from_bio_p12(pb->p12bio, NULL);
612     if (!TEST_ptr(p12)) {
613         pb->success = 0;
614         return;
615     }
616     pb->safes = PKCS12_unpack_authsafes(p12);
617     if (!TEST_ptr(pb->safes))
618         pb->success = 0;
619
620     pb->safe_idx = 0;
621     PKCS12_free(p12);
622 }
623
624 void start_check_pkcs12_with_mac(PKCS12_BUILDER *pb, const PKCS12_ENC *mac)
625 {
626     PKCS12 *p12 = from_bio_p12(pb->p12bio, mac); 
627     if (!TEST_ptr(p12)) {
628         pb->success = 0;
629         return;
630     }
631     pb->safes = PKCS12_unpack_authsafes(p12); 
632     if (!TEST_ptr(pb->safes)) 
633         pb->success = 0;
634
635     pb->safe_idx = 0;
636     PKCS12_free(p12);
637 }
638
639 void start_check_pkcs12_file(PKCS12_BUILDER *pb)
640 {
641     PKCS12 *p12 = read_p12(pb->filename, NULL);
642     if (!TEST_ptr(p12)) {
643         pb->success = 0;
644         return;
645     }
646     pb->safes = PKCS12_unpack_authsafes(p12);
647     if (!TEST_ptr(pb->safes))
648         pb->success = 0;
649
650     pb->safe_idx = 0;
651     PKCS12_free(p12);
652 }       
653         
654 void start_check_pkcs12_file_with_mac(PKCS12_BUILDER *pb, const PKCS12_ENC *mac)
655 {
656     PKCS12 *p12 = read_p12(pb->filename, mac);
657     if (!TEST_ptr(p12)) {
658         pb->success = 0;
659         return;
660     }
661     pb->safes = PKCS12_unpack_authsafes(p12);
662     if (!TEST_ptr(pb->safes))
663         pb->success = 0;
664
665     pb->safe_idx = 0;
666     PKCS12_free(p12);
667 }
668
669 void end_check_pkcs12(PKCS12_BUILDER *pb)
670 {
671     sk_PKCS7_pop_free(pb->safes, PKCS7_free);
672 }
673
674
675 void start_check_contentinfo(PKCS12_BUILDER *pb)
676 {
677     pb->bag_idx = 0;
678     pb->bags = decode_contentinfo(pb->safes, pb->safe_idx++, NULL);
679     if (!TEST_ptr(pb->bags)) {
680         pb->success = 0;
681         return;
682     }
683     TEST_info("Decoding %d bags", sk_PKCS12_SAFEBAG_num(pb->bags));
684 }
685
686 void start_check_contentinfo_encrypted(PKCS12_BUILDER *pb, const PKCS12_ENC *enc)
687 {
688     pb->bag_idx = 0;
689     pb->bags = decode_contentinfo(pb->safes, pb->safe_idx++, enc);
690     if (!TEST_ptr(pb->bags)) {
691         pb->success = 0;
692         return;
693     }
694     TEST_info("Decoding %d bags", sk_PKCS12_SAFEBAG_num(pb->bags));
695 }
696
697
698 void end_check_contentinfo(PKCS12_BUILDER *pb)
699 {
700     if (!TEST_int_eq(sk_PKCS12_SAFEBAG_num(pb->bags), pb->bag_idx))
701         pb->success = 0;
702     sk_PKCS12_SAFEBAG_pop_free(pb->bags, PKCS12_SAFEBAG_free);
703     pb->bags = NULL;
704 }
705
706