diff options
-rw-r--r-- | lib/x509/common.c | 67 | ||||
-rw-r--r-- | lib/x509/common.h | 2 | ||||
-rw-r--r-- | lib/x509/pkcs12.c | 60 | ||||
-rw-r--r-- | lib/x509/pkcs12.h | 5 | ||||
-rw-r--r-- | lib/x509/pkcs12_bag.c | 133 | ||||
-rw-r--r-- | lib/x509/privkey_pkcs8.c | 16 |
6 files changed, 254 insertions, 29 deletions
diff --git a/lib/x509/common.c b/lib/x509/common.c index 05dde94c16..c65d4518de 100644 --- a/lib/x509/common.c +++ b/lib/x509/common.c @@ -778,3 +778,70 @@ gnutls_datum encoded; return 0; } + +/* Writes the value of the datum in the given ASN1_TYPE. If str is non + * zero it encodes it as OCTET STRING. + */ +int _gnutls_x509_write_value( ASN1_TYPE c, const char* root, + const gnutls_datum *data, int str) +{ +int result; +int asize; +ASN1_TYPE c2 = ASN1_TYPE_EMPTY; +gnutls_datum val; + + asize = data->size + 16; + + val.data = gnutls_malloc( asize); + if (val.data == NULL) { + gnutls_assert(); + result = GNUTLS_E_MEMORY_ERROR; + goto cleanup; + } + + if (str) { + /* Convert it to OCTET STRING + */ + if ((result=asn1_create_element + (_gnutls_get_pkix(), "PKIX1.pkcs-7-Data", &c2)) != ASN1_SUCCESS) { + gnutls_assert(); + result = _gnutls_asn2err(result); + goto cleanup; + } + + result = asn1_write_value(c2, "", data->data, data->size); + if (result != ASN1_SUCCESS) { + gnutls_assert(); + result = _gnutls_asn2err(result); + goto cleanup; + } + + result = _gnutls_x509_der_encode( c2, "", &val, 0); + if (result < 0) { + gnutls_assert(); + goto cleanup; + } + + } else { + val.data = data->data; + val.size = data->size; + } + + /* Write the data. + */ + result = asn1_write_value( c, root, val.data, val.size); + + if (val.data != data->data) + _gnutls_free_datum(&val); + + if (result != ASN1_SUCCESS) { + gnutls_assert(); + return _gnutls_asn2err(result); + } + + return 0; + + cleanup: + if (val.data != data->data) _gnutls_free_datum( &val); + return result; +} diff --git a/lib/x509/common.h b/lib/x509/common.h index c6f71e5866..0839544e95 100644 --- a/lib/x509/common.h +++ b/lib/x509/common.h @@ -51,4 +51,4 @@ int _gnutls_x509_export_int( ASN1_TYPE asn1_data, int tmp_buf_size, unsigned char* output_data, int* output_data_size); int _gnutls_x509_read_value( ASN1_TYPE c, const char* root, gnutls_datum *ret, int str); - +int _gnutls_x509_write_value( ASN1_TYPE c, const char* root, const gnutls_datum* data, int str); diff --git a/lib/x509/pkcs12.c b/lib/x509/pkcs12.c index bbec749116..54c87b2c76 100644 --- a/lib/x509/pkcs12.c +++ b/lib/x509/pkcs12.c @@ -234,7 +234,7 @@ int gnutls_pkcs12_export( gnutls_pkcs12 pkcs12, output_data, output_data_size); } -static int _oid2bag( const char* oid) +static int oid2bag( const char* oid) { if (strcmp(oid, BAG_PKCS8_KEY)==0) return GNUTLS_BAG_PKCS8_KEY; @@ -248,7 +248,7 @@ static int _oid2bag( const char* oid) return GNUTLS_BAG_UNKNOWN; } -static const char* _bag2oid( int bag) +static const char* bag2oid( int bag) { switch (bag) { case GNUTLS_BAG_PKCS8_KEY: @@ -321,7 +321,7 @@ char counter[MAX_INT_DIGITS]; /* Read the Bag type */ - bag_type = _oid2bag( oid); + bag_type = oid2bag( oid); if (bag_type < 0) { gnutls_assert(); @@ -342,6 +342,19 @@ char counter[MAX_INT_DIGITS]; goto cleanup; } + if (bag_type == GNUTLS_BAG_CERTIFICATE || + bag_type == GNUTLS_BAG_CRL) { + gnutls_datum tmp = bag->data[i]; + + result = _pkcs12_decode_crt_bag( bag_type, &tmp, &bag->data[i]); + if (result < 0) { + gnutls_assert(); + goto cleanup; + } + + _gnutls_free_datum( &tmp); + } + bag->type[i] = bag_type; } @@ -745,8 +758,10 @@ int result; int i; const char* oid; - if (enc) - *enc = 0; + if (bag->type[0] == GNUTLS_BAG_ENCRYPTED && enc) { + *enc = 1; + return 0; /* ENCRYPTED BAG, do nothing. */ + } else if (enc) *enc = 0; /* Step 1. Create the SEQUENCE. */ @@ -760,9 +775,7 @@ const char* oid; for (i=0;i<bag->bag_elements;i++) { - if (bag->type[i] == GNUTLS_BAG_ENCRYPTED && enc) *enc = 1; - - oid = _bag2oid( bag->type[i]); + oid = bag2oid( bag->type[i]); if (oid==NULL) { gnutls_assert(); continue; @@ -793,14 +806,37 @@ const char* oid; goto cleanup; } - /* Copy the Bag Value */ - result = asn1_write_value( c2, "?LAST.bagValue", bag->data[i].data, bag->data[i].size); - if (result != ASN1_SUCCESS) { + if (bag->type[i] == GNUTLS_BAG_CERTIFICATE || + bag->type[i] == GNUTLS_BAG_CRL) { + gnutls_datum tmp; + + /* in that case encode it to a CertBag or + * a CrlBag. + */ + + result = _pkcs12_encode_crt_bag( bag->type[i], &bag->data[i], &tmp); + + if (result < 0) { + gnutls_assert(); + goto cleanup; + } + + result = _gnutls_x509_write_value( c2, "?LAST.bagValue", + &tmp, 0); + + _gnutls_free_datum( &tmp); + + } else { + + result = _gnutls_x509_write_value( c2, "?LAST.bagValue", + &bag->data[i], 0); + } + + if (result < 0) { gnutls_assert(); - result = _gnutls_asn2err(result); goto cleanup; } diff --git a/lib/x509/pkcs12.h b/lib/x509/pkcs12.h index f8a4084f29..97542ff9d2 100644 --- a/lib/x509/pkcs12.h +++ b/lib/x509/pkcs12.h @@ -68,3 +68,8 @@ int _pkcs12_check_pass( const char* pass, size_t plen); int _pkcs12_encode_safe_contents( gnutls_pkcs12_bag bag, ASN1_TYPE* content, int *enc); + +int _pkcs12_decode_crt_bag( gnutls_pkcs12_bag_type type, const gnutls_datum* in, + gnutls_datum* out); +int _pkcs12_encode_crt_bag( gnutls_pkcs12_bag_type type, const gnutls_datum* raw, + gnutls_datum* out); diff --git a/lib/x509/pkcs12_bag.c b/lib/x509/pkcs12_bag.c index 0484049cd1..55de2e5954 100644 --- a/lib/x509/pkcs12_bag.c +++ b/lib/x509/pkcs12_bag.c @@ -119,6 +119,138 @@ int gnutls_pkcs12_bag_get_data(gnutls_pkcs12_bag bag, int indx, gnutls_datum* da return 0; } +#define X509_CERT_OID "1.2.840.113549.1.9.22.1" +#define X509_CRL_OID "1.2.840.113549.1.9.23.1" + +int _pkcs12_decode_crt_bag( gnutls_pkcs12_bag_type type, const gnutls_datum* in, + gnutls_datum* out) +{ + int ret; + ASN1_TYPE c2 = ASN1_TYPE_EMPTY; + + if (type == GNUTLS_BAG_CERTIFICATE) { + if ((ret=asn1_create_element(_gnutls_get_pkix(), + "PKIX1.pkcs-12-CertBag", &c2)) != ASN1_SUCCESS) { + gnutls_assert(); + ret = _gnutls_asn2err(ret); + goto cleanup; + } + + ret = asn1_der_decoding( &c2, in->data, in->size, NULL); + if (ret != ASN1_SUCCESS) { + gnutls_assert(); + ret = _gnutls_asn2err(ret); + goto cleanup; + } + + ret = _gnutls_x509_read_value( c2, "certValue", out, 1); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + } else { /* CRL */ + if ((ret=asn1_create_element(_gnutls_get_pkix(), + "PKIX1.pkcs-12-CRLBag", &c2)) != ASN1_SUCCESS) { + gnutls_assert(); + ret = _gnutls_asn2err(ret); + goto cleanup; + } + + ret = asn1_der_decoding( &c2, in->data, in->size, NULL); + if (ret != ASN1_SUCCESS) { + gnutls_assert(); + ret = _gnutls_asn2err(ret); + goto cleanup; + } + + ret = _gnutls_x509_read_value( c2, "crlValue", out, 1); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + } + + asn1_delete_structure( &c2); + + return 0; + + + cleanup: + + asn1_delete_structure( &c2); + return ret; +} + + +int _pkcs12_encode_crt_bag( gnutls_pkcs12_bag_type type, const gnutls_datum* raw, + gnutls_datum* out) +{ + int ret; + ASN1_TYPE c2 = ASN1_TYPE_EMPTY; + + if (type == GNUTLS_BAG_CERTIFICATE) { + if ((ret=asn1_create_element(_gnutls_get_pkix(), + "PKIX1.pkcs-12-CertBag", &c2)) != ASN1_SUCCESS) { + gnutls_assert(); + ret = _gnutls_asn2err(ret); + goto cleanup; + } + + ret = asn1_write_value( c2, "certId", X509_CERT_OID, 1); + if (ret != ASN1_SUCCESS) { + gnutls_assert(); + ret = _gnutls_asn2err(ret); + goto cleanup; + } + + ret = _gnutls_x509_write_value( c2, "certValue", raw, 1); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + } else { /* CRL */ + if ((ret=asn1_create_element(_gnutls_get_pkix(), + "PKIX1.pkcs-12-CRLBag", &c2)) != ASN1_SUCCESS) { + gnutls_assert(); + ret = _gnutls_asn2err(ret); + goto cleanup; + } + + ret = asn1_write_value( c2, "crlId", X509_CRL_OID, 1); + if (ret != ASN1_SUCCESS) { + gnutls_assert(); + ret = _gnutls_asn2err(ret); + goto cleanup; + } + + ret = _gnutls_x509_write_value( c2, "crlValue", raw, 1); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + } + + ret = _gnutls_x509_der_encode( c2, "", out, 0); + + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + asn1_delete_structure( &c2); + + return 0; + + + cleanup: + + asn1_delete_structure( &c2); + return ret; +} + + /** * gnutls_pkcs12_bag_set_data - This function inserts data into the bag * @bag: The bag @@ -154,6 +286,7 @@ int ret; } ret = _gnutls_set_datum( &bag->data[bag->bag_elements], data->data, data->size); + if (ret < 0) { gnutls_assert(); return ret; diff --git a/lib/x509/privkey_pkcs8.c b/lib/x509/privkey_pkcs8.c index 048382865c..f195678bcf 100644 --- a/lib/x509/privkey_pkcs8.c +++ b/lib/x509/privkey_pkcs8.c @@ -1658,22 +1658,6 @@ int _gnutls_pkcs7_decrypt_data(const gnutls_datum * data, goto error; } -#if 1 -/* not really needed - */ - len = sizeof(enc_oid); - result = - asn1_read_value(pkcs7_asn, - "encryptedContentInfo.contentType", - enc_oid, &len); - if (result != ASN1_SUCCESS) { - gnutls_assert(); - result = _gnutls_asn2err(result); - goto error; - } - _gnutls_x509_log("PKCS #7 encryptedContentInfo.contentType OID '%s'.\n", enc_oid); -#endif - /* Check the encryption schema OID */ len = sizeof(enc_oid); |