From: Andreas Steffen Date: Mon, 6 May 2019 12:33:49 +0000 (+0200) Subject: pki: Allow inclusion of [unsupported] critical X.509 extension X-Git-Tag: 5.8.0rc1~5^2~8 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=df6441a13f5894c8152ebbbb2b680f2762cf3d07;p=thirdparty%2Fstrongswan.git pki: Allow inclusion of [unsupported] critical X.509 extension --- diff --git a/src/libstrongswan/credentials/builder.c b/src/libstrongswan/credentials/builder.c index 61dfbbcada..a663636ea5 100644 --- a/src/libstrongswan/credentials/builder.c +++ b/src/libstrongswan/credentials/builder.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2008 Martin Willi - * Copyright (C) 2016 Andreas Steffen + * Copyright (C) 2016-2019 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -75,5 +75,6 @@ ENUM(builder_part_names, BUILD_FROM_FILE, BUILD_END, "BUILD_THRESHOLD", "BUILD_EDDSA_PUB", "BUILD_EDDSA_PRIV_ASN1_DER", + "BUILD_CRITICAL_EXTENSION", "BUILD_END", ); diff --git a/src/libstrongswan/credentials/builder.h b/src/libstrongswan/credentials/builder.h index b283bd166f..b623646562 100644 --- a/src/libstrongswan/credentials/builder.h +++ b/src/libstrongswan/credentials/builder.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2008 Martin Willi - * Copyright (C) 2016 Andreas Steffen + * Copyright (C) 2016-2019 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -160,6 +160,8 @@ enum builder_part_t { BUILD_EDDSA_PUB, /** DER encoded ASN.1 EdDSA private key */ BUILD_EDDSA_PRIV_ASN1_DER, + /** OID of an [unsupported] critical extension */ + BUILD_CRITICAL_EXTENSION, /** end of variable argument builder list */ BUILD_END, }; diff --git a/src/libstrongswan/plugins/x509/x509_cert.c b/src/libstrongswan/plugins/x509/x509_cert.c index f3d4377d8d..731170886b 100644 --- a/src/libstrongswan/plugins/x509/x509_cert.c +++ b/src/libstrongswan/plugins/x509/x509_cert.c @@ -171,6 +171,11 @@ struct private_x509_cert_t { */ chunk_t authKeySerialNumber; + /** + * Optional OID of an [unsupported] critical extension + */ + chunk_t critical_extension_oid; + /** * Path Length Constraint */ @@ -1951,6 +1956,7 @@ METHOD(certificate_t, destroy, void, chunk_free(&this->authKeyIdentifier); chunk_free(&this->encoding); chunk_free(&this->encoding_hash); + chunk_free(&this->critical_extension_oid); if (!this->parsed) { /* only parsed certificates point these fields to "encoded" */ chunk_free(&this->signature); @@ -2203,6 +2209,7 @@ static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert, 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; identification_t *issuer, *subject; chunk_t key_info; hasher_t *hasher; @@ -2570,17 +2577,25 @@ static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert, chunk_from_thing(cert->inhibit_any)))); } + if (cert->critical_extension_oid.len > 0) + { + criticalExtension = asn1_wrap(ASN1_SEQUENCE, "mmm", + asn1_simple_object(ASN1_OID, cert->critical_extension_oid), + asn1_simple_object(ASN1_BOOLEAN, chunk_from_chars(0xFF)), + asn1_simple_object(ASN1_OCTET_STRING, chunk_empty)); + } + if (basicConstraints.ptr || subjectAltNames.ptr || authKeyIdentifier.ptr || crlDistributionPoints.ptr || nameConstraints.ptr || ipAddrBlocks.ptr) { extensions = asn1_wrap(ASN1_CONTEXT_C_3, "m", - asn1_wrap(ASN1_SEQUENCE, "mmmmmmmmmmmmmm", + asn1_wrap(ASN1_SEQUENCE, "mmmmmmmmmmmmmmm", basicConstraints, keyUsage, subjectKeyIdentifier, authKeyIdentifier, subjectAltNames, extendedKeyUsage, crlDistributionPoints, authorityInfoAccess, nameConstraints, certPolicies, policyMappings, policyConstraints, inhibitAnyPolicy, - ipAddrBlocks)); + ipAddrBlocks, criticalExtension)); } cert->tbsCertificate = asn1_wrap(ASN1_SEQUENCE, "mmccmcmm", @@ -2864,6 +2879,9 @@ x509_cert_t *x509_cert_gen(certificate_type_t type, va_list args) case BUILD_DIGEST_ALG: digest_alg = va_arg(args, int); continue; + case BUILD_CRITICAL_EXTENSION: + cert->critical_extension_oid = chunk_clone(va_arg(args, chunk_t)); + continue; case BUILD_END: break; default: diff --git a/src/libstrongswan/plugins/x509/x509_crl.c b/src/libstrongswan/plugins/x509/x509_crl.c index 95cb11cf4f..a315c629de 100644 --- a/src/libstrongswan/plugins/x509/x509_crl.c +++ b/src/libstrongswan/plugins/x509/x509_crl.c @@ -116,6 +116,11 @@ struct private_x509_crl_t { */ chunk_t authKeySerialNumber; + /** + * Optional OID of an [unsupported] critical extension + */ + chunk_t critical_extension_oid; + /** * Number of BaseCRL, if a delta CRL */ @@ -605,6 +610,7 @@ METHOD(certificate_t, destroy, void, DESTROY_IF(this->issuer); free(this->authKeyIdentifier.ptr); free(this->encoding.ptr); + free(this->critical_extension_oid.ptr); if (this->generated) { free(this->crlNumber.ptr); @@ -718,7 +724,7 @@ static bool generate(private_x509_crl_t *this, certificate_t *cert, { chunk_t extensions = chunk_empty, certList = chunk_empty, serial; chunk_t crlDistributionPoints = chunk_empty, baseCrlNumber = chunk_empty; - chunk_t sig_scheme = chunk_empty; + chunk_t sig_scheme = chunk_empty, criticalExtension = chunk_empty; enumerator_t *enumerator; crl_reason_t reason; time_t date; @@ -784,8 +790,16 @@ static bool generate(private_x509_crl_t *this, certificate_t *cert, asn1_integer("c", this->baseCrlNumber))); } + if (this->critical_extension_oid.len > 0) + { + criticalExtension = asn1_wrap(ASN1_SEQUENCE, "mmm", + asn1_simple_object(ASN1_OID, this->critical_extension_oid), + asn1_simple_object(ASN1_BOOLEAN, chunk_from_chars(0xFF)), + asn1_simple_object(ASN1_OCTET_STRING, chunk_empty)); + } + extensions = asn1_wrap(ASN1_CONTEXT_C_0, "m", - asn1_wrap(ASN1_SEQUENCE, "mmmm", + asn1_wrap(ASN1_SEQUENCE, "mmmmm", asn1_wrap(ASN1_SEQUENCE, "mm", asn1_build_known_oid(OID_AUTHORITY_KEY_ID), asn1_wrap(ASN1_OCTET_STRING, "m", @@ -796,7 +810,8 @@ static bool generate(private_x509_crl_t *this, certificate_t *cert, asn1_build_known_oid(OID_CRL_NUMBER), asn1_wrap(ASN1_OCTET_STRING, "m", asn1_integer("c", this->crlNumber))), - crlDistributionPoints, baseCrlNumber)); + crlDistributionPoints, baseCrlNumber, + criticalExtension)); this->tbsCertList = asn1_wrap(ASN1_SEQUENCE, "cccmmmm", ASN1_INTEGER_1, @@ -887,6 +902,9 @@ x509_crl_t *x509_crl_gen(certificate_type_t type, va_list args) enumerator->destroy(enumerator); continue; } + case BUILD_CRITICAL_EXTENSION: + crl->critical_extension_oid = chunk_clone(va_arg(args, chunk_t)); + continue; case BUILD_END: break; default: diff --git a/src/pki/commands/issue.c b/src/pki/commands/issue.c index b117fa1713..4f11e7aa58 100644 --- a/src/pki/commands/issue.c +++ b/src/pki/commands/issue.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2009 Martin Willi - * Copyright (C) 2015-2017 Andreas Steffen + * Copyright (C) 2015-2019 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -77,6 +77,7 @@ static int issue() int inhibit_mapping = X509_NO_CONSTRAINT, require_explicit = X509_NO_CONSTRAINT; chunk_t serial = chunk_empty; chunk_t encoding = chunk_empty; + chunk_t critical_extension_oid = chunk_empty; time_t not_before, not_after, lifetime = 1095 * 24 * 60 * 60; char *datenb = NULL, *datena = NULL, *dateform = NULL; x509_flag_t flags = 0; @@ -333,6 +334,10 @@ static int issue() case 'o': ocsp->insert_last(ocsp, arg); continue; + case 'X': + chunk_free(&critical_extension_oid); + critical_extension_oid = asn1_oid_from_string(arg); + continue; case EOF: break; default: @@ -558,6 +563,7 @@ static int issue() BUILD_POLICY_REQUIRE_EXPLICIT, require_explicit, BUILD_POLICY_INHIBIT_MAPPING, inhibit_mapping, BUILD_POLICY_INHIBIT_ANY, inhibit_any, + BUILD_CRITICAL_EXTENSION, critical_extension_oid, BUILD_SIGNATURE_SCHEME, scheme, BUILD_END); if (!cert) @@ -593,6 +599,7 @@ end: cdps->destroy_function(cdps, (void*)destroy_cdp); ocsp->destroy(ocsp); signature_params_destroy(scheme); + free(critical_extension_oid.ptr); free(encoding.ptr); free(serial.ptr); @@ -612,6 +619,7 @@ usage: mappings->destroy_function(mappings, (void*)destroy_policy_mapping); cdps->destroy_function(cdps, (void*)destroy_cdp); ocsp->destroy(ocsp); + free(critical_extension_oid.ptr); return command_usage(error); } @@ -632,7 +640,7 @@ static void __attribute__ ((constructor))reg() "[--policy-explicit len] [--policy-inhibit len] [--policy-any len]", "[--cert-policy oid [--cps-uri uri] [--user-notice text]]+", "[--digest md5|sha1|sha224|sha256|sha384|sha512|sha3_224|sha3_256|sha3_384|sha3_512]", - "[--rsa-padding pkcs1|pss]", + "[--rsa-padding pkcs1|pss] [--critical oid]", "[--outform der|pem]"}, { {"help", 'h', 0, "show usage information"}, @@ -666,6 +674,7 @@ static void __attribute__ ((constructor))reg() {"ocsp", 'o', 1, "OCSP AuthorityInfoAccess URI to include"}, {"digest", 'g', 1, "digest for signature creation, default: key-specific"}, {"rsa-padding", 'R', 1, "padding for RSA signatures, default: pkcs1"}, + {"critical", 'X', 1, "critical extension OID to include"}, {"outform", 'f', 1, "encoding of generated cert, default: der"}, } }); diff --git a/src/pki/commands/self.c b/src/pki/commands/self.c index a08ee99316..31018e8054 100644 --- a/src/pki/commands/self.c +++ b/src/pki/commands/self.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2009 Martin Willi - * Copyright (C) 2015-2017 Andreas Steffen + * Copyright (C) 2015-2019 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -65,6 +65,7 @@ static int self() int require_explicit = X509_NO_CONSTRAINT; chunk_t serial = chunk_empty; chunk_t encoding = chunk_empty; + chunk_t critical_extension_oid = chunk_empty; time_t not_before, not_after, lifetime = 1095 * 24 * 60 * 60; char *datenb = NULL, *datena = NULL, *dateform = NULL; x509_flag_t flags = 0; @@ -289,6 +290,10 @@ static int self() case 'o': ocsp->insert_last(ocsp, arg); continue; + case 'X': + chunk_free(&critical_extension_oid); + critical_extension_oid = asn1_oid_from_string(arg); + continue; case EOF: break; default: @@ -399,6 +404,7 @@ static int self() BUILD_POLICY_REQUIRE_EXPLICIT, require_explicit, BUILD_POLICY_INHIBIT_MAPPING, inhibit_mapping, BUILD_POLICY_INHIBIT_ANY, inhibit_any, + BUILD_CRITICAL_EXTENSION, critical_extension_oid, BUILD_END); if (!cert) { @@ -430,6 +436,7 @@ end: mappings->destroy_function(mappings, (void*)destroy_policy_mapping); ocsp->destroy(ocsp); signature_params_destroy(scheme); + free(critical_extension_oid.ptr); free(encoding.ptr); free(serial.ptr); @@ -448,6 +455,7 @@ usage: policies->destroy_function(policies, (void*)destroy_cert_policy); mappings->destroy_function(mappings, (void*)destroy_policy_mapping); ocsp->destroy(ocsp); + free(critical_extension_oid.ptr); return command_usage(error); } @@ -468,7 +476,7 @@ static void __attribute__ ((constructor))reg() "[--policy-explicit len] [--policy-inhibit len] [--policy-any len]", "[--cert-policy oid [--cps-uri uri] [--user-notice text]]+", "[--digest md5|sha1|sha224|sha256|sha384|sha512|sha3_224|sha3_256|sha3_384|sha3_512]", - "[--rsa-padding pkcs1|pss]", + "[--rsa-padding pkcs1|pss] [--critical oid]", "[--outform der|pem]"}, { {"help", 'h', 0, "show usage information"}, @@ -498,6 +506,7 @@ static void __attribute__ ((constructor))reg() {"ocsp", 'o', 1, "OCSP AuthorityInfoAccess URI to include"}, {"digest", 'g', 1, "digest for signature creation, default: key-specific"}, {"rsa-padding", 'R', 1, "padding for RSA signatures, default: pkcs1"}, + {"critical", 'X', 1, "critical extension OID to include for test purposes"}, {"outform", 'f', 1, "encoding of generated cert, default: der"}, } }); diff --git a/src/pki/commands/signcrl.c b/src/pki/commands/signcrl.c index 8c234feb65..dfe1ce014a 100644 --- a/src/pki/commands/signcrl.c +++ b/src/pki/commands/signcrl.c @@ -2,7 +2,7 @@ * Copyright (C) 2010 Martin Willi * Copyright (C) 2010 revosec AG * - * Copyright (C) 2017 Andreas Steffen + * Copyright (C) 2017-2019 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ #include #include #include +#include /** @@ -133,6 +134,7 @@ static int sign_crl() enumerator_t *enumerator, *lastenum = NULL; x509_cdp_t *cdp; chunk_t crl_serial = chunk_empty, baseCrlNumber = chunk_empty; + chunk_t critical_extension_oid = chunk_empty; chunk_t encoding = chunk_empty; bool pss = lib->settings->get_bool(lib->settings, "%s.rsa_pss", FALSE, lib->ns); @@ -279,6 +281,10 @@ static int sign_crl() goto usage; } continue; + case 'X': + chunk_free(&critical_extension_oid); + critical_extension_oid = asn1_oid_from_string(arg); + continue; case EOF: break; default: @@ -414,6 +420,7 @@ static int sign_crl() BUILD_REVOKED_ENUMERATOR, enumerator, BUILD_REVOKED_ENUMERATOR, lastenum, BUILD_SIGNATURE_SCHEME, scheme, BUILD_CRL_DISTRIBUTION_POINTS, cdps, BUILD_BASE_CRL, baseCrlNumber, + BUILD_CRITICAL_EXTENSION, critical_extension_oid, BUILD_END); enumerator->destroy(enumerator); @@ -442,6 +449,7 @@ error: DESTROY_IF(lastenum); DESTROY_IF((certificate_t*)lastcrl); signature_params_destroy(scheme); + free(critical_extension_oid.ptr); free(encoding.ptr); free(baseCrlNumber.ptr); free(crl_serial.ptr); @@ -457,6 +465,7 @@ error: usage: list->destroy_function(list, (void*)revoked_destroy); cdps->destroy_function(cdps, (void*)x509_cdp_destroy); + free(critical_extension_oid.ptr); return command_usage(error); } @@ -474,7 +483,7 @@ static void __attribute__ ((constructor))reg() " superseded|cessation-of-operation|certificate-hold]", " [--date timestamp] --cert file|--serial hex]*", "[--digest md5|sha1|sha224|sha256|sha384|sha512|sha3_224|sha3_256|sha3_384|sha3_512]", - "[--rsa-padding pkcs1|pss]", + "[--rsa-padding pkcs1|pss] [--critical oid]", "[--outform der|pem]"}, { {"help", 'h', 0, "show usage information"}, @@ -494,6 +503,7 @@ static void __attribute__ ((constructor))reg() {"date", 'd', 1, "revocation date as unix timestamp, default: now"}, {"digest", 'g', 1, "digest for signature creation, default: key-specific"}, {"rsa-padding", 'R', 1, "padding for RSA signatures, default: pkcs1"}, + {"critical", 'X', 1, "critical extension OID to include for test purposes"}, {"outform", 'f', 1, "encoding of generated crl, default: der"}, } }); diff --git a/src/pki/man/pki---issue.1.in b/src/pki/man/pki---issue.1.in index 8aec653069..99dcaca703 100644 --- a/src/pki/man/pki---issue.1.in +++ b/src/pki/man/pki---issue.1.in @@ -1,4 +1,4 @@ -.TH "PKI \-\-ISSUE" 1 "2016-12-13" "@PACKAGE_VERSION@" "strongSwan" +.TH "PKI \-\-ISSUE" 1 "2019-05-06" "@PACKAGE_VERSION@" "strongSwan" . .SH "NAME" . @@ -24,9 +24,10 @@ pki \-\-issue \- Issue a certificate using a CA certificate and key .OP \-\-crl uri\ \fR[\fB\-\-crlissuer\ \fIissuer\fR] .OP \-\-ocsp uri .OP \-\-pathlen len -.OP \-\-nc-permitted name .OP \-\-addrblock block +.OP \-\-nc-permitted name .OP \-\-nc-excluded name +.OP \-\-critical oid .OP \-\-policy\-mapping mapping .OP \-\-policy\-explicit len .OP \-\-policy\-inhibit len @@ -181,6 +182,9 @@ or .B email: prefix to force a constraint type. .TP +.BI "\-X, \-\-critical " oid +Add a critical extension with the given OID. +.TP .BI "\-M, \-\-policy-mapping " issuer-oid:subject-oid Add policyMapping from issuer to subject OID. .TP diff --git a/src/pki/man/pki---self.1.in b/src/pki/man/pki---self.1.in index 5f7e42108b..6e04609785 100644 --- a/src/pki/man/pki---self.1.in +++ b/src/pki/man/pki---self.1.in @@ -1,4 +1,4 @@ -.TH "PKI \-\-SELF" 1 "2016-12-13" "@PACKAGE_VERSION@" "strongSwan" +.TH "PKI \-\-SELF" 1 "2019-05-06" "@PACKAGE_VERSION@" "strongSwan" . .SH "NAME" . @@ -26,6 +26,7 @@ pki \-\-self \- Create a self-signed certificate .OP \-\-addrblock block .OP \-\-nc-permitted name .OP \-\-nc-excluded name +.OP \-\-critical oid .OP \-\-policy\-mapping mapping .OP \-\-policy\-explicit len .OP \-\-policy\-inhibit len @@ -160,6 +161,9 @@ or .B email: prefix to force a constraint type. .TP +.BI "\-X, \-\-critical " oid +Add a critical extension with the given OID. +.TP .BI "\-M, \-\-policy-mapping " issuer-oid:subject-oid Add policyMapping from issuer to subject OID. .TP diff --git a/src/pki/man/pki---signcrl.1.in b/src/pki/man/pki---signcrl.1.in index 0abd166a9f..781de8bfa3 100644 --- a/src/pki/man/pki---signcrl.1.in +++ b/src/pki/man/pki---signcrl.1.in @@ -1,4 +1,4 @@ -.TH "PKI \-\-SIGNCRL" 1 "2013-08-12" "@PACKAGE_VERSION@" "strongSwan" +.TH "PKI \-\-SIGNCRL" 1 "2019-05-06" "@PACKAGE_VERSION@" "strongSwan" . .SH "NAME" . @@ -18,6 +18,7 @@ pki \-\-signcrl \- Issue a Certificate Revocation List (CRL) using a CA certific .OP \-\-digest digest .OP \-\-rsa\-padding padding .OP \fR[\fB\-\-reason\ \fIreason\fR]\ \fR[\fB\-\-date\ \fIts\fR]\ \fB\-\-cert\ \fIfile\fB|\-\-serial\ \fIhex\fR +.OP \-\-critical oid .OP \-\-outform encoding .OP \-\-debug level .YS @@ -107,6 +108,9 @@ determined based on the type and size of the signature key. Padding to use for RSA signatures. Either \fIpkcs1\fR or \fIpss\fR, defaults to \fIpkcs1\fR. .TP +.BI "\-X, \-\-critical " oid +Add a critical extension with the given OID. +.TP .BI "\-f, \-\-outform " encoding Encoding of the created certificate file. Either \fIder\fR (ASN.1 DER) or \fIpem\fR (Base64 PEM), defaults to \fIder\fR.