diff options
| author | tb <> | 2021-10-23 14:48:33 +0000 |
|---|---|---|
| committer | tb <> | 2021-10-23 14:48:33 +0000 |
| commit | 147506f7f8787695cb6f8cc2d28d08bc9f32534a (patch) | |
| tree | f1eee73077eef60165f5647e96778b173f5daa5c /src | |
| parent | e225ef6f6dede36e99d00cc89f0ea8c7da355d25 (diff) | |
| download | openbsd-147506f7f8787695cb6f8cc2d28d08bc9f32534a.tar.gz openbsd-147506f7f8787695cb6f8cc2d28d08bc9f32534a.tar.bz2 openbsd-147506f7f8787695cb6f8cc2d28d08bc9f32534a.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"); |
