]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
pki: Use X.509v3 EKU extension in CSR
authorAndreas Steffen <andreas.steffen@strongswan.org>
Wed, 11 Jan 2023 16:44:15 +0000 (17:44 +0100)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Wed, 11 Jan 2023 18:19:09 +0000 (19:19 +0100)
src/libstrongswan/plugins/x509/x509_cert.c
src/libstrongswan/plugins/x509/x509_pkcs10.c
src/pki/commands/req.c
src/pki/man/pki---issue.1.in
src/pki/man/pki---req.1.in

index 718832d1f184bd3fce370741c6b5b4af4f192d8a..6ff3f086e50ef2c78f0a3740287898bb4fcd5bbb 100644 (file)
@@ -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))
index 549f74dc4adc2c805f67676ca46e88af842d4eec..94a90ebf091f758d68a0cdee35fa6b9a4a676d23 100644 (file)
@@ -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);
index 43eec90011f8af1d22b2d1f543c732e0c1f86580..d9effb1d62f84c5ff41b71cd489be8217b0f68da 100644 (file)
@@ -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"},
index 3050c0e4ccb2dbc055e275e6196257f6bb65f87b..ae7a62ddd971c0c7e769fadfec055bbbf19ce499 100644 (file)
@@ -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,
index a988527c65e75cae311243fd94398e78da2a6a61..e25a809589217bed375eed33da52f581b1bfad07 100644 (file)
@@ -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