From: Andreas Steffen Date: Wed, 11 Jan 2023 16:44:15 +0000 (+0100) Subject: pki: Use X.509v3 EKU extension in CSR X-Git-Tag: android-2.4.0~9 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8effb06d6c674166a55e2996fc7f0a51421ac70c;p=thirdparty%2Fstrongswan.git pki: Use X.509v3 EKU extension in CSR --- diff --git a/src/libstrongswan/plugins/x509/x509_cert.c b/src/libstrongswan/plugins/x509/x509_cert.c index 718832d1f1..6ff3f086e5 100644 --- a/src/libstrongswan/plugins/x509/x509_cert.c +++ b/src/libstrongswan/plugins/x509/x509_cert.c @@ -769,10 +769,9 @@ static const asn1Object_t extendedKeyUsageObjects[] = { #define EXT_KEY_USAGE_PURPOSE_ID 1 /** - * Extracts extendedKeyUsage OIDs + * Extracts extendedKeyUsage OIDs (shared with x509_pkcs10.c) */ -static bool parse_extendedKeyUsage(chunk_t blob, int level0, - private_x509_cert_t *this) +bool x509_parse_eku_extension(chunk_t blob, int level0, x509_flag_t *flags) { asn1_parser_t *parser; chunk_t object; @@ -789,19 +788,19 @@ static bool parse_extendedKeyUsage(chunk_t blob, int level0, switch (asn1_known_oid(object)) { case OID_SERVER_AUTH: - this->flags |= X509_SERVER_AUTH; + *flags |= X509_SERVER_AUTH; break; case OID_CLIENT_AUTH: - this->flags |= X509_CLIENT_AUTH; + *flags |= X509_CLIENT_AUTH; break; case OID_IKE_INTERMEDIATE: - this->flags |= X509_IKE_INTERMEDIATE; + *flags |= X509_IKE_INTERMEDIATE; break; case OID_OCSP_SIGNING: - this->flags |= X509_OCSP_SIGNER; + *flags |= X509_OCSP_SIGNER; break; case OID_MS_SMARTCARD_LOGON: - this->flags |= X509_MS_SMARTCARD_LOGON; + *flags |= X509_MS_SMARTCARD_LOGON; break; default: break; @@ -1516,7 +1515,7 @@ static bool parse_certificate(private_x509_cert_t *this) parse_keyUsage(object, this); break; case OID_EXTENDED_KEY_USAGE: - if (!parse_extendedKeyUsage(object, level, this)) + if (!x509_parse_eku_extension(object, level, &this->flags)) { goto end; } @@ -2207,6 +2206,50 @@ static chunk_t generate_ts(traffic_selector_t *ts) return asn1_wrap(ASN1_SEQUENCE, "mm", from, to); } +/** + * Generate an extendedKeyUsage X.509v3 extension (shared with x509_pkcs10.c) + */ +chunk_t x509_generate_eku_extension(x509_flag_t flags) +{ + chunk_t extendedKeyUsage = chunk_empty, ocspSigning = chunk_empty; + chunk_t serverAuth = chunk_empty, clientAuth = chunk_empty; + chunk_t ikeIntermediate = chunk_empty, msSmartcardLogon = chunk_empty; + + if (flags & X509_SERVER_AUTH) + { + serverAuth = asn1_build_known_oid(OID_SERVER_AUTH); + } + if (flags & X509_CLIENT_AUTH) + { + clientAuth = asn1_build_known_oid(OID_CLIENT_AUTH); + } + if (flags & X509_IKE_INTERMEDIATE) + { + ikeIntermediate = asn1_build_known_oid(OID_IKE_INTERMEDIATE); + } + if (flags & X509_OCSP_SIGNER) + { + ocspSigning = asn1_build_known_oid(OID_OCSP_SIGNING); + } + if (flags & X509_MS_SMARTCARD_LOGON) + { + msSmartcardLogon = asn1_build_known_oid(OID_MS_SMARTCARD_LOGON); + } + + if (serverAuth.ptr || clientAuth.ptr || ikeIntermediate.ptr || + ocspSigning.ptr || msSmartcardLogon.ptr) + { + extendedKeyUsage = asn1_wrap(ASN1_SEQUENCE, "mm", + asn1_build_known_oid(OID_EXTENDED_KEY_USAGE), + asn1_wrap(ASN1_OCTET_STRING, "m", + asn1_wrap(ASN1_SEQUENCE, "mmmmm", + serverAuth, clientAuth, ikeIntermediate, + ocspSigning, msSmartcardLogon))); + } + + return extendedKeyUsage; +} + /** * Generate and sign a new certificate */ @@ -2215,18 +2258,15 @@ static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert, { const chunk_t keyUsageCrlSign = chunk_from_chars(0x01, 0x02); const chunk_t keyUsageCertSignCrlSign = chunk_from_chars(0x01, 0x06); - chunk_t extensions = chunk_empty, extendedKeyUsage = chunk_empty; - chunk_t serverAuth = chunk_empty, clientAuth = chunk_empty; - chunk_t ocspSigning = chunk_empty, certPolicies = chunk_empty; + chunk_t extensions = chunk_empty, certPolicies = chunk_empty; chunk_t basicConstraints = chunk_empty, nameConstraints = chunk_empty; chunk_t keyUsage = chunk_empty, keyUsageBits = chunk_empty; chunk_t subjectAltNames = chunk_empty, policyMappings = chunk_empty; chunk_t subjectKeyIdentifier = chunk_empty, authKeyIdentifier = chunk_empty; chunk_t crlDistributionPoints = chunk_empty, authorityInfoAccess = chunk_empty; chunk_t policyConstraints = chunk_empty, inhibitAnyPolicy = chunk_empty; - chunk_t ikeIntermediate = chunk_empty, msSmartcardLogon = chunk_empty; chunk_t ipAddrBlocks = chunk_empty, sig_scheme = chunk_empty; - chunk_t criticalExtension = chunk_empty; + chunk_t criticalExtension = chunk_empty, extendedKeyUsage = chunk_empty; identification_t *issuer, *subject; chunk_t key_info; hasher_t *hasher; @@ -2350,37 +2390,7 @@ static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert, } /* add extendedKeyUsage flags */ - if (cert->flags & X509_SERVER_AUTH) - { - serverAuth = asn1_build_known_oid(OID_SERVER_AUTH); - } - if (cert->flags & X509_CLIENT_AUTH) - { - clientAuth = asn1_build_known_oid(OID_CLIENT_AUTH); - } - if (cert->flags & X509_IKE_INTERMEDIATE) - { - ikeIntermediate = asn1_build_known_oid(OID_IKE_INTERMEDIATE); - } - if (cert->flags & X509_OCSP_SIGNER) - { - ocspSigning = asn1_build_known_oid(OID_OCSP_SIGNING); - } - if (cert->flags & X509_MS_SMARTCARD_LOGON) - { - msSmartcardLogon = asn1_build_known_oid(OID_MS_SMARTCARD_LOGON); - } - - if (serverAuth.ptr || clientAuth.ptr || ikeIntermediate.ptr || - ocspSigning.ptr || msSmartcardLogon.ptr) - { - extendedKeyUsage = asn1_wrap(ASN1_SEQUENCE, "mm", - asn1_build_known_oid(OID_EXTENDED_KEY_USAGE), - asn1_wrap(ASN1_OCTET_STRING, "m", - asn1_wrap(ASN1_SEQUENCE, "mmmmm", - serverAuth, clientAuth, ikeIntermediate, - ocspSigning, msSmartcardLogon))); - } + extendedKeyUsage = x509_generate_eku_extension(cert->flags); /* add subjectKeyIdentifier to CA and OCSP signer certificates */ if (cert->flags & (X509_CA | X509_OCSP_SIGNER | X509_CRL_SIGN)) diff --git a/src/libstrongswan/plugins/x509/x509_pkcs10.c b/src/libstrongswan/plugins/x509/x509_pkcs10.c index 549f74dc4a..94a90ebf09 100644 --- a/src/libstrongswan/plugins/x509/x509_pkcs10.c +++ b/src/libstrongswan/plugins/x509/x509_pkcs10.c @@ -77,6 +77,11 @@ struct private_x509_pkcs10_t { */ chunk_t certTypeExt; + /** + * extendedKeyUsage flags + */ + x509_flag_t flags; + /** * Signature scheme */ @@ -110,6 +115,10 @@ extern bool x509_parse_generalNames(chunk_t blob, int level0, bool implicit, linked_list_t *list); extern chunk_t x509_build_subjectAltNames(linked_list_t *list); +extern bool x509_parse_eku_extension(chunk_t blob, int level0, x509_flag_t *flags); + +extern chunk_t x509_generate_eku_extension(x509_flag_t flags); + METHOD(certificate_t, get_type, certificate_type_t, private_x509_pkcs10_t *this) { @@ -238,30 +247,31 @@ METHOD(pkcs10_t, get_challengePassword, chunk_t, METHOD(pkcs10_t, get_flags, x509_flag_t, private_x509_pkcs10_t *this) { - x509_flag_t flags = X509_NONE; - char *profile; + if (this->certTypeExt.len > 0) + { + char *profile; - profile = strndup(this->certTypeExt.ptr, this->certTypeExt.len); + profile = strndup(this->certTypeExt.ptr, this->certTypeExt.len); - if (strcaseeq(profile, "server")) - { - flags |= X509_SERVER_AUTH; - } - else if (strcaseeq(profile, "client")) - { - flags |= X509_CLIENT_AUTH; - } - else if (strcaseeq(profile, "dual")) - { - flags |= (X509_SERVER_AUTH | X509_CLIENT_AUTH); - } - else if (strcaseeq(profile, "ocsp")) - { - flags |= X509_OCSP_SIGNER; + if (strcaseeq(profile, "server")) + { + this->flags |= X509_SERVER_AUTH; + } + else if (strcaseeq(profile, "client")) + { + this->flags |= X509_CLIENT_AUTH; + } + else if (strcaseeq(profile, "dual")) + { + this->flags |= (X509_SERVER_AUTH | X509_CLIENT_AUTH); + } + else if (strcaseeq(profile, "ocsp")) + { + this->flags |= X509_OCSP_SIGNER; + } + free(profile); } - free(profile); - - return flags; + return this->flags; } METHOD(pkcs10_t, create_subjectAltName_enumerator, enumerator_t*, @@ -279,6 +289,7 @@ static bool generate(private_x509_pkcs10_t *cert, private_key_t *sign_key, chunk_t key_info, subjectAltNames, attributes; chunk_t extensionRequest = chunk_empty, certTypeExt = chunk_empty; chunk_t challengePassword = chunk_empty, sig_scheme = chunk_empty; + chunk_t extendedKeyUsage = chunk_empty; identification_t *subject; subject = cert->subject; @@ -322,13 +333,17 @@ static bool generate(private_x509_pkcs10_t *cert, private_key_t *sign_key, )); } + /* encode extendedKeyUsage flags */ + extendedKeyUsage = x509_generate_eku_extension(cert->flags); + /* encode extensionRequest attribute */ if (subjectAltNames.ptr || certTypeExt.ptr) { extensionRequest = asn1_wrap(ASN1_SEQUENCE, "mm", asn1_build_known_oid(OID_EXTENSION_REQUEST), asn1_wrap(ASN1_SET, "m", - asn1_wrap(ASN1_SEQUENCE, "mm", subjectAltNames, certTypeExt) + asn1_wrap(ASN1_SEQUENCE, "mmm", + subjectAltNames, certTypeExt, extendedKeyUsage) )); } @@ -452,6 +467,12 @@ static bool parse_extension_request(private_x509_pkcs10_t *this, chunk_t blob, i } this->certTypeExt = object; break; + case OID_EXTENDED_KEY_USAGE: + if (!x509_parse_eku_extension(object, level, &this->flags)) + { + goto end; + } + break; default: break; } @@ -769,6 +790,9 @@ x509_pkcs10_t *x509_pkcs10_gen(certificate_type_t type, va_list args) case BUILD_CERT_TYPE_EXT: cert->certTypeExt = chunk_clone(va_arg(args, chunk_t)); continue; + case BUILD_X509_FLAG: + cert->flags |= va_arg(args, x509_flag_t); + continue; case BUILD_SIGNATURE_SCHEME: cert->scheme = va_arg(args, signature_params_t*); cert->scheme = signature_params_clone(cert->scheme); diff --git a/src/pki/commands/req.c b/src/pki/commands/req.c index 43eec90011..d9effb1d62 100644 --- a/src/pki/commands/req.c +++ b/src/pki/commands/req.c @@ -43,6 +43,7 @@ static int req() chunk_t encoding = chunk_empty; chunk_t challenge_password = chunk_empty; chunk_t cert_type_ext = chunk_empty; + x509_flag_t flags = 0; char *arg; bool pss = lib->settings->get_bool(lib->settings, "%s.rsa_pss", FALSE, lib->ns); @@ -78,6 +79,24 @@ static int req() goto usage; } continue; + case 'e': + if (streq(arg, "serverAuth")) + { + flags |= X509_SERVER_AUTH; + } + else if (streq(arg, "clientAuth")) + { + flags |= X509_CLIENT_AUTH; + } + else if (streq(arg, "ocspSigning")) + { + flags |= X509_OCSP_SIGNER; + } + else if (streq(arg, "msSmartcardLogon")) + { + flags |= X509_MS_SMARTCARD_LOGON; + } + continue; case 'g': /* --digest */ if (!enum_from_name(hash_algorithm_short_names, arg, &digest)) { @@ -213,6 +232,7 @@ static int req() BUILD_SUBJECT, id, BUILD_SUBJECT_ALTNAMES, san, BUILD_CHALLENGE_PWD, challenge_password, + BUILD_X509_FLAG, flags, BUILD_CERT_TYPE_EXT, cert_type_ext, BUILD_SIGNATURE_SCHEME, scheme, BUILD_END); @@ -264,6 +284,7 @@ static void __attribute__ ((constructor))reg() "create a PKCS#10 certificate request", {"[--in file|--keyid hex] [--type rsa|ecdsa|bliss|priv]", " --oldreq file|--dn distinguished-name [--san subjectAltName]+", + "[--flag serverAuth|clientAuth|ocspSigning|msSmartcardLogon]+", "[--profile server|client|dual|ocsp] [--password challengePassword]", "[--digest sha1|sha224|sha256|sha384|sha512|sha3_224|sha3_256|sha3_384|sha3_512]", "[--rsa-padding pkcs1|pss] [--outform der|pem]"}, @@ -275,6 +296,7 @@ static void __attribute__ ((constructor))reg() {"oldreq", 'o', 1, "old certificate request to be used as a template"}, {"dn", 'd', 1, "subject distinguished name"}, {"san", 'a', 1, "subjectAltName to include in cert request"}, + {"flag", 'e', 1, "include extendedKeyUsage flag"}, {"profile", 'P', 1, "certificate profile name to include in cert request"}, {"password", 'p', 1, "challengePassword to include in cert request"}, {"digest", 'g', 1, "digest for signature creation, default: key-specific"}, diff --git a/src/pki/man/pki---issue.1.in b/src/pki/man/pki---issue.1.in index 3050c0e4cc..ae7a62ddd9 100644 --- a/src/pki/man/pki---issue.1.in +++ b/src/pki/man/pki---issue.1.in @@ -125,7 +125,8 @@ Serial number in hex. It is randomly allocated by default. .TP .BI "\-e, \-\-flag " flag Add extendedKeyUsage flag. One of \fIserverAuth\fR, \fIclientAuth\fR, -\fIcrlSign\fR, or \fIocspSigning\fR. Can be used multiple times. +\fIcrlSign\fR, \fIocspSigning\fR or \fImsSmartcardLogon\fR. Can be used multiple +times. .TP .BI "\-g, \-\-digest " digest Digest to use for signature creation. One of \fImd5\fR, \fIsha1\fR, diff --git a/src/pki/man/pki---req.1.in b/src/pki/man/pki---req.1.in index a988527c65..e25a809589 100644 --- a/src/pki/man/pki---req.1.in +++ b/src/pki/man/pki---req.1.in @@ -14,6 +14,7 @@ pki \-\-req \- Create a PKCS#10 certificate request .BI \-\-dn\~ distinguished-name .OP \-\-san subjectAltName .OP \-\-profile profile +.OP \-\-flag flag .OP \-\-password password .OP \-\-digest digest .OP \-\-rsa\-padding padding @@ -91,6 +92,11 @@ UTF8 string. Supported e.g. by translated into corresponding Extended Key Usage (EKU) flags in the generated X.509 certificate. .TP +.BI "\-e, \-\-flag " flag +Add extendedKeyUsage flag. One of \fIserverAuth\fR, \fIclientAuth\fR, +\fIocspSigning\fR or \fImsSmartcardLogon\fR. Can be used multiple times. Adds an +X.509v3 EKU extension containing these flags to the certificate request. +.TP .BI "\-p, \-\-password " password The challengePassword to include in the certificate request. .TP