summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/x509/common.c67
-rw-r--r--lib/x509/common.h2
-rw-r--r--lib/x509/pkcs12.c60
-rw-r--r--lib/x509/pkcs12.h5
-rw-r--r--lib/x509/pkcs12_bag.c133
-rw-r--r--lib/x509/privkey_pkcs8.c16
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);