/** * gnutls_pkcs7_get_crl_count: * @pkcs7: should contain a gnutls_pkcs7_t structure * * This function will return the number of certifcates in the PKCS7 * or RFC2630 crl set. * * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a * negative error value. **/ int gnutls_pkcs7_get_crl_count (gnutls_pkcs7_t pkcs7) { ASN1_TYPE c2 = ASN1_TYPE_EMPTY; int result, count; if (pkcs7 == NULL) return GNUTLS_E_INVALID_REQUEST; /* Step 1. decode the signed data. */ result = _decode_pkcs7_signed_data (pkcs7->pkcs7, &c2, NULL); if (result < 0) { gnutls_assert (); return result; } /* Step 2. Count the CertificateSet */ result = asn1_number_of_elements (c2, "crls", &count); asn1_delete_structure (&c2); if (result != ASN1_SUCCESS) { gnutls_assert (); return 0; /* no crls */ } return count; }
int _gnutls_x509_get_dn(ASN1_TYPE asn1_struct, const char *asn1_rdn_name, gnutls_datum_t * dn, unsigned flags) { gnutls_buffer_st out_str; int i, k1, result; _gnutls_buffer_init(&out_str); result = asn1_number_of_elements(asn1_struct, asn1_rdn_name, &k1); if (result != ASN1_SUCCESS) { if (result == ASN1_ELEMENT_NOT_FOUND || result == ASN1_VALUE_NOT_FOUND) { result = gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); } else { gnutls_assert(); result = _gnutls_asn2err(result); } goto cleanup; } if (k1 == 0) { gnutls_assert(); result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; goto cleanup; } if (flags & GNUTLS_X509_DN_FLAG_COMPAT) { for (i=0;i<k1;i++) { result = append_elements(asn1_struct, asn1_rdn_name, &out_str, i+1, (i==(k1-1))?1:0); if (result < 0) { gnutls_assert(); goto cleanup; } } } else { while (k1 > 0) { result = append_elements(asn1_struct, asn1_rdn_name, &out_str, k1, k1==1?1:0); if (result < 0) { gnutls_assert(); goto cleanup; } k1--; } } return _gnutls_buffer_to_datum(&out_str, dn, 1); cleanup: _gnutls_buffer_clear(&out_str); return result; }
/** * gnutls_x509_crl_get_crt_count: * @crl: should contain a #gnutls_x509_crl_t structure * * This function will return the number of revoked certificates in the * given CRL. * * Returns: number of certificates, a negative error code on failure. **/ int gnutls_x509_crl_get_crt_count(gnutls_x509_crl_t crl) { int count, result; if (crl == NULL) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } result = asn1_number_of_elements(crl->crl, "tbsCertList.revokedCertificates", &count); if (result != ASN1_SUCCESS) { gnutls_assert(); return 0; /* no certificates */ } return count; }
/* Decodes the SafeContents, and puts the output in * the given bag. */ int _pkcs12_decode_safe_contents (const gnutls_datum_t * content, gnutls_pkcs12_bag_t bag) { char oid[MAX_OID_SIZE], root[ASN1_MAX_NAME_SIZE]; ASN1_TYPE c2 = ASN1_TYPE_EMPTY; int len, result; int bag_type; gnutls_datum_t attr_val; int count = 0, i, attributes, j; size_t size; /* Step 1. Extract the SEQUENCE. */ if ((result = asn1_create_element (_gnutls_get_pkix (), "PKIX1.pkcs-12-SafeContents", &c2)) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } result = asn1_der_decoding (&c2, content->data, content->size, NULL); if (result != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } /* Count the number of bags */ result = asn1_number_of_elements (c2, "", &count); if (result != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } bag->bag_elements = MIN (MAX_BAG_ELEMENTS, count); for (i = 0; i < bag->bag_elements; i++) { snprintf (root, sizeof (root), "?%u.bagId", i + 1); len = sizeof (oid); result = asn1_read_value (c2, root, oid, &len); if (result != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } /* Read the Bag type */ bag_type = oid2bag (oid); if (bag_type < 0) { gnutls_assert (); goto cleanup; } /* Read the Bag Value */ snprintf (root, sizeof (root), "?%u.bagValue", i + 1); result = _gnutls_x509_read_value (c2, root, &bag->element[i].data, 0); if (result < 0) { gnutls_assert (); goto cleanup; } if (bag_type == GNUTLS_BAG_CERTIFICATE || bag_type == GNUTLS_BAG_CRL || bag_type == GNUTLS_BAG_SECRET) { gnutls_datum_t tmp = bag->element[i].data; result = _pkcs12_decode_crt_bag (bag_type, &tmp, &bag->element[i].data); if (result < 0) { gnutls_assert (); goto cleanup; } _gnutls_free_datum (&tmp); } /* read the bag attributes */ snprintf (root, sizeof (root), "?%u.bagAttributes", i + 1); result = asn1_number_of_elements (c2, root, &attributes); if (result != ASN1_SUCCESS && result != ASN1_ELEMENT_NOT_FOUND) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } if (attributes < 0) attributes = 1; if (result != ASN1_ELEMENT_NOT_FOUND) for (j = 0; j < attributes; j++) { snprintf (root, sizeof (root), "?%u.bagAttributes.?%u", i + 1, j + 1); result = _gnutls_x509_decode_and_read_attribute (c2, root, oid, sizeof (oid), &attr_val, 1, 0); if (result < 0) { gnutls_assert (); continue; /* continue in case we find some known attributes */ } if (strcmp (oid, KEY_ID_OID) == 0) { size = attr_val.size; result = _gnutls_x509_decode_octet_string (NULL, attr_val.data, size, attr_val.data, &size); attr_val.size = size; if (result < 0) { _gnutls_free_datum (&attr_val); gnutls_assert (); _gnutls_x509_log ("Error decoding PKCS12 Bag Attribute OID '%s'\n", oid); continue; } bag->element[i].local_key_id = attr_val; } else if (strcmp (oid, FRIENDLY_NAME_OID) == 0) { size = attr_val.size; result = _gnutls_x509_decode_octet_string ("BMPString", attr_val.data, size, attr_val.data, &size); attr_val.size = size; if (result < 0) { _gnutls_free_datum (&attr_val); gnutls_assert (); _gnutls_x509_log ("Error decoding PKCS12 Bag Attribute OID '%s'\n", oid); continue; } bag->element[i].friendly_name = ucs2_to_ascii (attr_val.data, attr_val.size); } else { _gnutls_free_datum (&attr_val); _gnutls_x509_log ("Unknown PKCS12 Bag Attribute OID '%s'\n", oid); } } bag->element[i].type = bag_type; } asn1_delete_structure (&c2); return 0; cleanup: if (c2) asn1_delete_structure (&c2); return result; }
bool p11_openssl_canon_name_der (p11_dict *asn1_defs, p11_buffer *der) { p11_buffer value; char outer[64]; char field[64]; node_asn *name; void *at; int value_len; bool failed; size_t offset; int ret; int num; int len; int i, j; name = p11_asn1_decode (asn1_defs, "PKIX1.Name", der->data, der->len, NULL); return_val_if_fail (name != NULL, false); ret = asn1_number_of_elements (name, "rdnSequence", &num); return_val_if_fail (ret == ASN1_SUCCESS, false); p11_buffer_init (&value, 0); p11_buffer_reset (der, 0); for (i = 1, failed = false; !failed && i < num + 1; i++) { snprintf (outer, sizeof (outer), "rdnSequence.?%d", i); for (j = 1; !failed; j++) { snprintf (field, sizeof (field), "%s.?%d.value", outer, j); value_len = 0; ret = asn1_read_value (name, field, NULL, &value_len); if (ret == ASN1_ELEMENT_NOT_FOUND) break; return_val_if_fail (ret == ASN1_MEM_ERROR, false); if (!p11_buffer_reset (&value, value_len)) return_val_if_reached (false); ret = asn1_read_value (name, field, value.data, &value_len); return_val_if_fail (ret == ASN1_SUCCESS, false); value.len = value_len; if (p11_openssl_canon_string_der (&value)) { ret = asn1_write_value (name, field, value.data, value.len); return_val_if_fail (ret == ASN1_SUCCESS, false); } else { failed = true; } } /* * Yes the OpenSSL canon strangeness, is a concatenation * of all the RelativeDistinguishedName DER encodings, without * an outside wrapper. */ if (!failed) { len = -1; ret = asn1_der_coding (name, outer, NULL, &len, NULL); return_val_if_fail (ret == ASN1_MEM_ERROR, false); offset = der->len; at = p11_buffer_append (der, len); return_val_if_fail (at != NULL, false); ret = asn1_der_coding (name, outer, at, &len, NULL); return_val_if_fail (ret == ASN1_SUCCESS, false); der->len = offset + len; } } asn1_delete_structure (&name); p11_buffer_uninit (&value); return !failed; }
static int append_elements(ASN1_TYPE asn1_struct, const char *asn1_rdn_name, gnutls_buffer_st *str, int k1, unsigned last) { int k2, result, max_k2; int len; uint8_t value[MAX_STRING_LEN]; char tmpbuffer1[ASN1_MAX_NAME_SIZE]; char tmpbuffer2[ASN1_MAX_NAME_SIZE]; char tmpbuffer3[ASN1_MAX_NAME_SIZE]; const char *ldap_desc; char oid[MAX_OID_SIZE]; gnutls_datum_t td = { NULL, 0 }; gnutls_datum_t tvd = { NULL, 0 }; /* create a string like "tbsCertList.issuer.rdnSequence.?1" */ if (asn1_rdn_name[0] != 0) snprintf(tmpbuffer1, sizeof(tmpbuffer1), "%s.?%u", asn1_rdn_name, k1); else snprintf(tmpbuffer1, sizeof(tmpbuffer1), "?%u", k1); len = sizeof(value) - 1; result = asn1_read_value(asn1_struct, tmpbuffer1, value, &len); if (result != ASN1_VALUE_NOT_FOUND && result != ASN1_SUCCESS) { /* expected */ gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } k2 = 0; result = asn1_number_of_elements(asn1_struct, tmpbuffer1, &max_k2); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } do { /* Move to the attibute type and values */ k2++; if (tmpbuffer1[0] != 0) snprintf(tmpbuffer2, sizeof(tmpbuffer2), "%s.?%u", tmpbuffer1, k2); else snprintf(tmpbuffer2, sizeof(tmpbuffer2), "?%u", k2); /* Try to read the RelativeDistinguishedName attributes. */ len = sizeof(value) - 1; result = asn1_read_value(asn1_struct, tmpbuffer2, value, &len); if (result == ASN1_ELEMENT_NOT_FOUND) break; if (result != ASN1_VALUE_NOT_FOUND && result != ASN1_SUCCESS) { /* expected */ gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } /* Read the OID */ _gnutls_str_cpy(tmpbuffer3, sizeof(tmpbuffer3), tmpbuffer2); _gnutls_str_cat(tmpbuffer3, sizeof(tmpbuffer3), ".type"); len = sizeof(oid) - 1; result = asn1_read_value(asn1_struct, tmpbuffer3, oid, &len); if (result == ASN1_ELEMENT_NOT_FOUND) break; else if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } /* Read the Value */ _gnutls_str_cpy(tmpbuffer3, sizeof(tmpbuffer3), tmpbuffer2); _gnutls_str_cat(tmpbuffer3, sizeof(tmpbuffer3), ".value"); len = 0; result = _gnutls_x509_read_value(asn1_struct, tmpbuffer3, &tvd); if (result < 0) { gnutls_assert(); goto cleanup; } #define STR_APPEND(y) if ((result=_gnutls_buffer_append_str( str, y)) < 0) { \ gnutls_assert(); \ goto cleanup; \ } #define DATA_APPEND(x,y) if ((result=_gnutls_buffer_append_data( str, x,y)) < 0) { \ gnutls_assert(); \ goto cleanup; \ } /* The encodings of adjoining RelativeDistinguishedNames are separated * by a comma character (',' ASCII 44). */ ldap_desc = gnutls_x509_dn_oid_name(oid, GNUTLS_X509_DN_OID_RETURN_OID); STR_APPEND(ldap_desc); STR_APPEND("="); result = _gnutls_x509_dn_to_string(oid, tvd.data, tvd.size, &td); if (result < 0) { gnutls_assert(); _gnutls_debug_log ("Cannot parse OID: '%s' with value '%s'\n", oid, _gnutls_bin2hex(tvd.data, tvd.size, tmpbuffer3, sizeof (tmpbuffer3), NULL)); goto cleanup; } DATA_APPEND(td.data, td.size); _gnutls_free_datum(&td); _gnutls_free_datum(&tvd); /* Where there is a multi-valued RDN, the outputs from adjoining * AttributeTypeAndValues are separated by a plus ('+' ASCII 43) * character. */ if (k2 < max_k2) { STR_APPEND("+"); } else if (!last) { STR_APPEND(","); } } while (1); result = 0; cleanup: _gnutls_free_datum(&td); _gnutls_free_datum(&tvd); return result; }