diff options
author | tb <> | 2021-10-23 14:48:33 +0000 |
---|---|---|
committer | tb <> | 2021-10-23 14:48:33 +0000 |
commit | bbbf84f2ed93d2384ef90bd8529a667c3f8cbc46 (patch) | |
tree | f1eee73077eef60165f5647e96778b173f5daa5c /src | |
parent | 48d78838532f827ee48f8f73f24be6e77d4bbf0f (diff) | |
download | openbsd-bbbf84f2ed93d2384ef90bd8529a667c3f8cbc46.tar.gz openbsd-bbbf84f2ed93d2384ef90bd8529a667c3f8cbc46.tar.bz2 openbsd-bbbf84f2ed93d2384ef90bd8529a667c3f8cbc46.zip |
Prepare pcks12 for opaque structs in libcrypto
get_cert_chain() needs some error checking. return X509_V_ errors
instead of trying to overload the NULL and then whine in a comment that
this won't really work.
Fix a bug that printed only the first attribute by factoring out the
thing that did the actual printing.
Sprinkle a few changes to accessors here and there.
This is loosely based on what OpenSSL did with some simplifications by
jsing.
ok beck jsing
Diffstat (limited to 'src')
-rw-r--r-- | src/usr.bin/openssl/pkcs12.c | 139 |
1 files changed, 70 insertions, 69 deletions
diff --git a/src/usr.bin/openssl/pkcs12.c b/src/usr.bin/openssl/pkcs12.c index d2e677ad84..4d5c0bbf21 100644 --- a/src/usr.bin/openssl/pkcs12.c +++ b/src/usr.bin/openssl/pkcs12.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: pkcs12.c,v 1.14 2019/07/26 12:35:59 inoguchi Exp $ */ | 1 | /* $OpenBSD: pkcs12.c,v 1.15 2021/10/23 14:48:33 tb Exp $ */ |
2 | /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL | 2 | /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL |
3 | * project. | 3 | * project. |
4 | */ | 4 | */ |
@@ -84,10 +84,10 @@ int dump_certs_pkeys_bags(BIO *out, STACK_OF(PKCS12_SAFEBAG) *bags, char *pass, | |||
84 | int passlen, int options, char *pempass); | 84 | int passlen, int options, char *pempass); |
85 | int dump_certs_pkeys_bag(BIO *out, PKCS12_SAFEBAG *bags, char *pass, | 85 | int dump_certs_pkeys_bag(BIO *out, PKCS12_SAFEBAG *bags, char *pass, |
86 | int passlen, int options, char *pempass); | 86 | int passlen, int options, char *pempass); |
87 | int print_attribs(BIO *out, STACK_OF(X509_ATTRIBUTE) *attrlst, | 87 | int print_attribs(BIO *out, const STACK_OF(X509_ATTRIBUTE) *attrlst, |
88 | const char *name); | 88 | const char *name); |
89 | void hex_prin(BIO *out, unsigned char *buf, int len); | 89 | void hex_prin(BIO *out, unsigned char *buf, int len); |
90 | int alg_print(BIO *x, X509_ALGOR *alg); | 90 | int alg_print(BIO *x, const X509_ALGOR *alg); |
91 | int cert_load(BIO *in, STACK_OF(X509) *sk); | 91 | int cert_load(BIO *in, STACK_OF(X509) *sk); |
92 | static int set_pbe(BIO *err, int *ppbe, const char *str); | 92 | static int set_pbe(BIO *err, int *ppbe, const char *str); |
93 | 93 | ||
@@ -692,7 +692,7 @@ pkcs12_main(int argc, char **argv) | |||
692 | vret = get_cert_chain(ucert, store, &chain2); | 692 | vret = get_cert_chain(ucert, store, &chain2); |
693 | X509_STORE_free(store); | 693 | X509_STORE_free(store); |
694 | 694 | ||
695 | if (!vret) { | 695 | if (vret == X509_V_OK) { |
696 | /* Exclude verified certificate */ | 696 | /* Exclude verified certificate */ |
697 | for (i = 1; i < sk_X509_num(chain2); i++) | 697 | for (i = 1; i < sk_X509_num(chain2); i++) |
698 | sk_X509_push(certs, sk_X509_value( | 698 | sk_X509_push(certs, sk_X509_value( |
@@ -701,7 +701,7 @@ pkcs12_main(int argc, char **argv) | |||
701 | X509_free(sk_X509_value(chain2, 0)); | 701 | X509_free(sk_X509_value(chain2, 0)); |
702 | sk_X509_free(chain2); | 702 | sk_X509_free(chain2); |
703 | } else { | 703 | } else { |
704 | if (vret >= 0) | 704 | if (vret != X509_V_ERR_UNSPECIFIED) |
705 | BIO_printf(bio_err, | 705 | BIO_printf(bio_err, |
706 | "Error %s getting chain.\n", | 706 | "Error %s getting chain.\n", |
707 | X509_verify_cert_error_string( | 707 | X509_verify_cert_error_string( |
@@ -895,9 +895,9 @@ dump_certs_pkeys_bag(BIO *out, PKCS12_SAFEBAG *bag, char *pass, | |||
895 | return 1; | 895 | return 1; |
896 | print_attribs(out, bag->attrib, "Bag Attributes"); | 896 | print_attribs(out, bag->attrib, "Bag Attributes"); |
897 | p8 = bag->value.keybag; | 897 | p8 = bag->value.keybag; |
898 | if (!(pkey = EVP_PKCS82PKEY(p8))) | 898 | if ((pkey = EVP_PKCS82PKEY(p8)) == NULL) |
899 | return 0; | 899 | return 0; |
900 | print_attribs(out, p8->attributes, "Key Attributes"); | 900 | print_attribs(out, PKCS8_pkey_get0_attrs(p8), "Key Attributes"); |
901 | PEM_write_bio_PrivateKey(out, pkey, pkcs12_config.enc, NULL, 0, | 901 | PEM_write_bio_PrivateKey(out, pkey, pkcs12_config.enc, NULL, 0, |
902 | NULL, pempass); | 902 | NULL, pempass); |
903 | EVP_PKEY_free(pkey); | 903 | EVP_PKEY_free(pkey); |
@@ -917,7 +917,7 @@ dump_certs_pkeys_bag(BIO *out, PKCS12_SAFEBAG *bag, char *pass, | |||
917 | PKCS8_PRIV_KEY_INFO_free(p8); | 917 | PKCS8_PRIV_KEY_INFO_free(p8); |
918 | return 0; | 918 | return 0; |
919 | } | 919 | } |
920 | print_attribs(out, p8->attributes, "Key Attributes"); | 920 | print_attribs(out, PKCS8_pkey_get0_attrs(p8), "Key Attributes"); |
921 | PKCS8_PRIV_KEY_INFO_free(p8); | 921 | PKCS8_PRIV_KEY_INFO_free(p8); |
922 | PEM_write_bio_PrivateKey(out, pkey, pkcs12_config.enc, NULL, 0, | 922 | PEM_write_bio_PrivateKey(out, pkey, pkcs12_config.enc, NULL, 0, |
923 | NULL, pempass); | 923 | NULL, pempass); |
@@ -962,43 +962,33 @@ dump_certs_pkeys_bag(BIO *out, PKCS12_SAFEBAG *bag, char *pass, | |||
962 | } | 962 | } |
963 | 963 | ||
964 | /* Given a single certificate return a verified chain or NULL if error */ | 964 | /* Given a single certificate return a verified chain or NULL if error */ |
965 | |||
966 | /* Hope this is OK .... */ | ||
967 | |||
968 | int | 965 | int |
969 | get_cert_chain(X509 *cert, X509_STORE *store, STACK_OF(X509) **chain) | 966 | get_cert_chain(X509 *cert, X509_STORE *store, STACK_OF(X509) **out_chain) |
970 | { | 967 | { |
971 | X509_STORE_CTX store_ctx; | 968 | X509_STORE_CTX *store_ctx = NULL; |
972 | STACK_OF(X509) *chn; | 969 | STACK_OF(X509) *chain = NULL; |
973 | int i = 0; | 970 | int ret = X509_V_ERR_UNSPECIFIED; |
974 | 971 | ||
975 | /* | 972 | if ((store_ctx = X509_STORE_CTX_new()) == NULL) |
976 | * FIXME: Should really check the return status of | ||
977 | * X509_STORE_CTX_init for an error, but how that fits into the | ||
978 | * return value of this function is less obvious. | ||
979 | */ | ||
980 | X509_STORE_CTX_init(&store_ctx, store, cert, NULL); | ||
981 | if (X509_verify_cert(&store_ctx) <= 0) { | ||
982 | i = X509_STORE_CTX_get_error(&store_ctx); | ||
983 | if (i == 0) | ||
984 | /* | ||
985 | * avoid returning 0 if X509_verify_cert() did not | ||
986 | * set an appropriate error value in the context | ||
987 | */ | ||
988 | i = -1; | ||
989 | chn = NULL; | ||
990 | goto err; | 973 | goto err; |
991 | } else | 974 | if (!X509_STORE_CTX_init(store_ctx, store, cert, NULL)) |
992 | chn = X509_STORE_CTX_get1_chain(&store_ctx); | 975 | goto err; |
976 | |||
977 | if (X509_verify_cert(store_ctx) > 0) { | ||
978 | if ((chain = X509_STORE_CTX_get1_chain(store_ctx)) == NULL) | ||
979 | goto err; | ||
980 | } | ||
981 | ret = X509_STORE_CTX_get_error(store_ctx); | ||
982 | |||
993 | err: | 983 | err: |
994 | X509_STORE_CTX_cleanup(&store_ctx); | 984 | X509_STORE_CTX_free(store_ctx); |
995 | *chain = chn; | 985 | *out_chain = chain; |
996 | 986 | ||
997 | return i; | 987 | return ret; |
998 | } | 988 | } |
999 | 989 | ||
1000 | int | 990 | int |
1001 | alg_print(BIO *x, X509_ALGOR *alg) | 991 | alg_print(BIO *x, const X509_ALGOR *alg) |
1002 | { | 992 | { |
1003 | PBEPARAM *pbe; | 993 | PBEPARAM *pbe; |
1004 | const unsigned char *p; | 994 | const unsigned char *p; |
@@ -1031,14 +1021,45 @@ cert_load(BIO *in, STACK_OF(X509) *sk) | |||
1031 | } | 1021 | } |
1032 | 1022 | ||
1033 | /* Generalised attribute print: handle PKCS#8 and bag attributes */ | 1023 | /* Generalised attribute print: handle PKCS#8 and bag attributes */ |
1024 | void | ||
1025 | print_attribute(BIO *out, const ASN1_TYPE *av) | ||
1026 | { | ||
1027 | char *value; | ||
1028 | |||
1029 | switch (av->type) { | ||
1030 | case V_ASN1_BMPSTRING: | ||
1031 | value = OPENSSL_uni2asc( | ||
1032 | av->value.bmpstring->data, | ||
1033 | av->value.bmpstring->length); | ||
1034 | BIO_printf(out, "%s\n", value); | ||
1035 | free(value); | ||
1036 | break; | ||
1037 | |||
1038 | case V_ASN1_OCTET_STRING: | ||
1039 | hex_prin(out, av->value.octet_string->data, | ||
1040 | av->value.octet_string->length); | ||
1041 | BIO_printf(out, "\n"); | ||
1042 | break; | ||
1043 | |||
1044 | case V_ASN1_BIT_STRING: | ||
1045 | hex_prin(out, av->value.bit_string->data, | ||
1046 | av->value.bit_string->length); | ||
1047 | BIO_printf(out, "\n"); | ||
1048 | break; | ||
1049 | |||
1050 | default: | ||
1051 | BIO_printf(out, "<Unsupported tag %d>\n", | ||
1052 | av->type); | ||
1053 | break; | ||
1054 | } | ||
1055 | } | ||
1034 | 1056 | ||
1035 | int | 1057 | int |
1036 | print_attribs(BIO *out, STACK_OF(X509_ATTRIBUTE) *attrlst, const char *name) | 1058 | print_attribs(BIO *out, const STACK_OF(X509_ATTRIBUTE) *attrlst, const char *name) |
1037 | { | 1059 | { |
1038 | X509_ATTRIBUTE *attr; | 1060 | X509_ATTRIBUTE *attr; |
1039 | ASN1_TYPE *av; | 1061 | ASN1_TYPE *av; |
1040 | char *value; | 1062 | int i, j, attr_nid; |
1041 | int i, attr_nid; | ||
1042 | if (!attrlst) { | 1063 | if (!attrlst) { |
1043 | BIO_printf(out, "%s: <No Attributes>\n", name); | 1064 | BIO_printf(out, "%s: <No Attributes>\n", name); |
1044 | return 1; | 1065 | return 1; |
@@ -1049,42 +1070,22 @@ print_attribs(BIO *out, STACK_OF(X509_ATTRIBUTE) *attrlst, const char *name) | |||
1049 | } | 1070 | } |
1050 | BIO_printf(out, "%s\n", name); | 1071 | BIO_printf(out, "%s\n", name); |
1051 | for (i = 0; i < sk_X509_ATTRIBUTE_num(attrlst); i++) { | 1072 | for (i = 0; i < sk_X509_ATTRIBUTE_num(attrlst); i++) { |
1073 | ASN1_OBJECT *obj; | ||
1074 | |||
1052 | attr = sk_X509_ATTRIBUTE_value(attrlst, i); | 1075 | attr = sk_X509_ATTRIBUTE_value(attrlst, i); |
1053 | attr_nid = OBJ_obj2nid(attr->object); | 1076 | obj = X509_ATTRIBUTE_get0_object(attr); |
1077 | attr_nid = OBJ_obj2nid(X509_ATTRIBUTE_get0_object(attr)); | ||
1054 | BIO_printf(out, " "); | 1078 | BIO_printf(out, " "); |
1055 | if (attr_nid == NID_undef) { | 1079 | if (attr_nid == NID_undef) { |
1056 | i2a_ASN1_OBJECT(out, attr->object); | 1080 | i2a_ASN1_OBJECT(out, obj); |
1057 | BIO_printf(out, ": "); | 1081 | BIO_printf(out, ": "); |
1058 | } else | 1082 | } else |
1059 | BIO_printf(out, "%s: ", OBJ_nid2ln(attr_nid)); | 1083 | BIO_printf(out, "%s: ", OBJ_nid2ln(attr_nid)); |
1060 | 1084 | ||
1061 | if (sk_ASN1_TYPE_num(attr->value.set)) { | 1085 | if (X509_ATTRIBUTE_count(attr)) { |
1062 | av = sk_ASN1_TYPE_value(attr->value.set, 0); | 1086 | for (j = 0; j < X509_ATTRIBUTE_count(attr); j++) { |
1063 | switch (av->type) { | 1087 | av = X509_ATTRIBUTE_get0_type(attr, j); |
1064 | case V_ASN1_BMPSTRING: | 1088 | print_attribute(out, av); |
1065 | value = OPENSSL_uni2asc( | ||
1066 | av->value.bmpstring->data, | ||
1067 | av->value.bmpstring->length); | ||
1068 | BIO_printf(out, "%s\n", value); | ||
1069 | free(value); | ||
1070 | break; | ||
1071 | |||
1072 | case V_ASN1_OCTET_STRING: | ||
1073 | hex_prin(out, av->value.octet_string->data, | ||
1074 | av->value.octet_string->length); | ||
1075 | BIO_printf(out, "\n"); | ||
1076 | break; | ||
1077 | |||
1078 | case V_ASN1_BIT_STRING: | ||
1079 | hex_prin(out, av->value.bit_string->data, | ||
1080 | av->value.bit_string->length); | ||
1081 | BIO_printf(out, "\n"); | ||
1082 | break; | ||
1083 | |||
1084 | default: | ||
1085 | BIO_printf(out, "<Unsupported tag %d>\n", | ||
1086 | av->type); | ||
1087 | break; | ||
1088 | } | 1089 | } |
1089 | } else | 1090 | } else |
1090 | BIO_printf(out, "<No Values>\n"); | 1091 | BIO_printf(out, "<No Values>\n"); |