From edf30136b0048122dccbbc4c9a6f967ce081752c Mon Sep 17 00:00:00 2001 From: Andreas Steffen Date: Tue, 15 Sep 2009 21:55:44 +0200 Subject: [PATCH] implemented ASN.1 encoding of PKCS#10 attributes --- src/libstrongswan/plugins/x509/x509_cert.c | 96 ++++++++++++-------- src/libstrongswan/plugins/x509/x509_pkcs10.c | 51 +++++++++-- 2 files changed, 97 insertions(+), 50 deletions(-) diff --git a/src/libstrongswan/plugins/x509/x509_cert.c b/src/libstrongswan/plugins/x509/x509_cert.c index 58ee3c061..17681823d 100644 --- a/src/libstrongswan/plugins/x509/x509_cert.c +++ b/src/libstrongswan/plugins/x509/x509_cert.c @@ -1173,6 +1173,58 @@ static private_x509_cert_t* create_empty(void) return this; } +/** + * Encode a linked list of subjectAltNames + */ +chunk_t x509_build_subjectAltNames(linked_list_t *list) +{ + chunk_t subjectAltNames = chunk_empty; + enumerator_t *enumerator; + identification_t *id; + + if (list->get_count(list) == 0) + { + return chunk_empty; + } + + enumerator = list->create_enumerator(list); + while (enumerator->enumerate(enumerator, &id)) + { + int context; + chunk_t name; + + switch (id->get_type(id)) + { + case ID_RFC822_ADDR: + context = ASN1_CONTEXT_S_1; + break; + case ID_FQDN: + context = ASN1_CONTEXT_S_2; + break; + case ID_IPV4_ADDR: + case ID_IPV6_ADDR: + context = ASN1_CONTEXT_S_7; + break; + default: + DBG1("encoding %N as subjectAltName not supported", + id_type_names, id->get_type(id)); + enumerator->destroy(enumerator); + free(subjectAltNames.ptr); + return chunk_empty; + } + name = asn1_wrap(context, "c", id->get_encoding(id)); + subjectAltNames = chunk_cat("mm", subjectAltNames, name); + } + enumerator->destroy(enumerator); + + return asn1_wrap(ASN1_SEQUENCE, "mm", + asn1_build_known_oid(OID_SUBJECT_ALT_NAME), + asn1_wrap(ASN1_OCTET_STRING, "m", + asn1_wrap(ASN1_SEQUENCE, "m", subjectAltNames) + ) + ); +} + /** * Generate and sign a new certificate */ @@ -1188,7 +1240,6 @@ static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert, signature_scheme_t scheme; hasher_t *hasher; enumerator_t *enumerator; - identification_t *id; char *uri; subject = cert->subject; @@ -1234,43 +1285,8 @@ static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert, return FALSE; } - enumerator = cert->subjectAltNames->create_enumerator(cert->subjectAltNames); - while (enumerator->enumerate(enumerator, &id)) - { - int context; - chunk_t name; - - switch (id->get_type(id)) - { - case ID_RFC822_ADDR: - context = ASN1_CONTEXT_S_1; - break; - case ID_FQDN: - context = ASN1_CONTEXT_S_2; - break; - case ID_IPV4_ADDR: - case ID_IPV6_ADDR: - context = ASN1_CONTEXT_S_7; - break; - default: - DBG1("encoding %N as subjectAltName not supported", - id_type_names, id->get_type(id)); - enumerator->destroy(enumerator); - free(key_info.ptr); - free(subjectAltNames.ptr); - return FALSE; - } - name = asn1_wrap(context, "c", id->get_encoding(id)); - subjectAltNames = chunk_cat("mm", subjectAltNames, name); - } - enumerator->destroy(enumerator); - if (subjectAltNames.ptr) - { - subjectAltNames = asn1_wrap(ASN1_SEQUENCE, "mm", - asn1_build_known_oid(OID_SUBJECT_ALT_NAME), - asn1_wrap(ASN1_OCTET_STRING, "m", - asn1_wrap(ASN1_SEQUENCE, "m", subjectAltNames))); - } + /* encode subjectAltNames */ + subjectAltNames = x509_build_subjectAltNames(cert->subjectAltNames); /* encode CRL distribution points extension */ enumerator = cert->crl_uris->create_enumerator(cert->crl_uris); @@ -1472,8 +1488,8 @@ x509_cert_t *x509_cert_gen(certificate_type_t type, va_list args) enumerator = list->create_enumerator(list); while (enumerator->enumerate(enumerator, &id)) { - cert->subjectAltNames->insert_last( - cert->subjectAltNames, id->clone(id)); + cert->subjectAltNames->insert_last(cert->subjectAltNames, + id->clone(id)); } enumerator->destroy(enumerator); continue; diff --git a/src/libstrongswan/plugins/x509/x509_pkcs10.c b/src/libstrongswan/plugins/x509/x509_pkcs10.c index 15393cc7f..6d750c98c 100644 --- a/src/libstrongswan/plugins/x509/x509_pkcs10.c +++ b/src/libstrongswan/plugins/x509/x509_pkcs10.c @@ -98,6 +98,12 @@ struct private_x509_pkcs10_t { refcount_t ref; }; +/** + * Imported from x509_cert.c + */ +extern void x509_parse_generalNames(chunk_t blob, int level0, bool implicit, linked_list_t *list); +extern chunk_t x509_build_subjectAltNames(linked_list_t *list); + /** * Implementation of certificate_t.get_type. */ @@ -249,11 +255,6 @@ static enumerator_t* create_subjectAltName_enumerator(private_x509_pkcs10_t *thi return this->subjectAltNames->create_enumerator(this->subjectAltNames); } -/** - * Imported from x509_cert.c - */ -extern void x509_parse_generalNames(chunk_t blob, int level0, bool implicit, linked_list_t *list); - /** * ASN.1 definition of a PKCS#10 extension request */ @@ -538,8 +539,9 @@ static private_x509_pkcs10_t* create_empty(void) static bool generate(private_x509_pkcs10_t *cert, private_key_t *sign_key, int digest_alg) { - chunk_t attributes = chunk_empty; - chunk_t key_info; + chunk_t key_info, subjectAltNames, attributes; + chunk_t extensionRequest = chunk_empty; + chunk_t challengePassword = chunk_empty; signature_scheme_t scheme; identification_t *subject; @@ -561,11 +563,37 @@ static bool generate(private_x509_pkcs10_t *cert, private_key_t *sign_key, return FALSE; } + /* encode subjectAltNames */ + subjectAltNames = x509_build_subjectAltNames(cert->subjectAltNames); + + if (subjectAltNames.ptr) + { + extensionRequest = asn1_wrap(ASN1_SEQUENCE, "mm", + asn1_build_known_oid(OID_EXTENSION_REQUEST), + asn1_wrap(ASN1_SET, "m", + asn1_wrap(ASN1_SEQUENCE, "m", subjectAltNames) + )); + } + if (cert->challengePassword.len > 0) + { + asn1_t type = asn1_is_printablestring(cert->challengePassword) ? + ASN1_PRINTABLESTRING : ASN1_T61STRING; + + challengePassword = asn1_wrap(ASN1_SEQUENCE, "mm", + asn1_build_known_oid(OID_CHALLENGE_PASSWORD), + asn1_wrap(ASN1_SET, "m", + asn1_simple_object(type, cert->challengePassword) + ) + ); + } + attributes = asn1_wrap(ASN1_CONTEXT_C_0, "mm", extensionRequest, + challengePassword); + cert->certificationRequestInfo = asn1_wrap(ASN1_SEQUENCE, "ccmm", ASN1_INTEGER_0, subject->get_encoding(subject), key_info, - asn1_wrap(ASN1_CONTEXT_C_0, "m", attributes)); + attributes); if (!sign_key->sign(sign_key, scheme, cert->certificationRequestInfo, &cert->signature)) @@ -648,12 +676,15 @@ x509_pkcs10_t *x509_pkcs10_gen(certificate_type_t type, va_list args) enumerator = list->create_enumerator(list); while (enumerator->enumerate(enumerator, &id)) { - cert->subjectAltNames->insert_last( - cert->subjectAltNames, id->clone(id)); + cert->subjectAltNames->insert_last(cert->subjectAltNames, + id->clone(id)); } enumerator->destroy(enumerator); continue; } + case BUILD_PASSPHRASE: + cert->challengePassword = chunk_clone(va_arg(args, chunk_t)); + continue; case BUILD_DIGEST_ALG: digest_alg = va_arg(args, int); continue;