/src/boringssl/crypto/x509/v3_akey.cc
Line | Count | Source |
1 | | // Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | | // you may not use this file except in compliance with the License. |
5 | | // You may obtain a copy of the License at |
6 | | // |
7 | | // https://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software |
10 | | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | | // See the License for the specific language governing permissions and |
13 | | // limitations under the License. |
14 | | |
15 | | #include <stdio.h> |
16 | | #include <string.h> |
17 | | |
18 | | #include <openssl/asn1.h> |
19 | | #include <openssl/asn1t.h> |
20 | | #include <openssl/conf.h> |
21 | | #include <openssl/err.h> |
22 | | #include <openssl/mem.h> |
23 | | #include <openssl/obj.h> |
24 | | #include <openssl/x509.h> |
25 | | |
26 | | #include "internal.h" |
27 | | |
28 | | |
29 | | using namespace bssl; |
30 | | |
31 | | static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_KEYID( |
32 | | const X509V3_EXT_METHOD *method, void *ext, STACK_OF(CONF_VALUE) *extlist); |
33 | | static void *v2i_AUTHORITY_KEYID(const X509V3_EXT_METHOD *method, |
34 | | const X509V3_CTX *ctx, |
35 | | const STACK_OF(CONF_VALUE) *values); |
36 | | |
37 | | const X509V3_EXT_METHOD bssl::v3_akey_id = { |
38 | | NID_authority_key_identifier, |
39 | | X509V3_EXT_MULTILINE, |
40 | | ASN1_ITEM_ref(AUTHORITY_KEYID), |
41 | | nullptr, |
42 | | nullptr, |
43 | | nullptr, |
44 | | nullptr, |
45 | | nullptr, |
46 | | nullptr, |
47 | | i2v_AUTHORITY_KEYID, |
48 | | v2i_AUTHORITY_KEYID, |
49 | | nullptr, |
50 | | nullptr, |
51 | | nullptr, |
52 | | }; |
53 | | |
54 | | static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_KEYID( |
55 | 306 | const X509V3_EXT_METHOD *method, void *ext, STACK_OF(CONF_VALUE) *extlist) { |
56 | 306 | const AUTHORITY_KEYID *akeyid = |
57 | 306 | reinterpret_cast<const AUTHORITY_KEYID *>(ext); |
58 | 306 | int extlist_was_null = extlist == nullptr; |
59 | 306 | if (akeyid->keyid) { |
60 | 195 | char *tmp = x509v3_bytes_to_hex(akeyid->keyid->data, akeyid->keyid->length); |
61 | 195 | int ok = tmp != nullptr && X509V3_add_value("keyid", tmp, &extlist); |
62 | 195 | OPENSSL_free(tmp); |
63 | 195 | if (!ok) { |
64 | 0 | goto err; |
65 | 0 | } |
66 | 195 | } |
67 | 306 | if (akeyid->issuer) { |
68 | 75 | STACK_OF(CONF_VALUE) *tmpextlist = |
69 | 75 | i2v_GENERAL_NAMES(nullptr, akeyid->issuer, extlist); |
70 | 75 | if (tmpextlist == nullptr) { |
71 | 12 | goto err; |
72 | 12 | } |
73 | 63 | extlist = tmpextlist; |
74 | 63 | } |
75 | 294 | if (akeyid->serial) { |
76 | 116 | if (!X509V3_add_value_int("serial", akeyid->serial, &extlist)) { |
77 | 0 | goto err; |
78 | 0 | } |
79 | 116 | } |
80 | 294 | return extlist; |
81 | | |
82 | 12 | err: |
83 | 12 | if (extlist_was_null) { |
84 | 12 | sk_CONF_VALUE_pop_free(extlist, X509V3_conf_free); |
85 | 12 | } |
86 | 12 | return nullptr; |
87 | 294 | } |
88 | | |
89 | | // Currently two options: |
90 | | // |
91 | | // - keyid: Use the issuer's subject key ID. The value 'always' means it's an |
92 | | // error if the issuer certificate doesn't have one. |
93 | | // |
94 | | // - issuer: Use the issuer's issuer and serial number. The default is to only |
95 | | // use this if the key ID is not present. The value 'always' means it's always |
96 | | // included. |
97 | | static void *v2i_AUTHORITY_KEYID(const X509V3_EXT_METHOD *method, |
98 | | const X509V3_CTX *ctx, |
99 | 0 | const STACK_OF(CONF_VALUE) *values) { |
100 | 0 | enum Option { kOff = 0, kOn = 1, kAlways = 2 }; |
101 | 0 | Option use_key_id = kOff, use_issuer = kOff; |
102 | 0 | for (const CONF_VALUE *cnf : values) { |
103 | 0 | if (!strcmp(cnf->name, "keyid")) { |
104 | 0 | use_key_id = kOn; |
105 | 0 | if (cnf->value && !strcmp(cnf->value, "always")) { |
106 | 0 | use_key_id = kAlways; |
107 | 0 | } |
108 | 0 | } else if (!strcmp(cnf->name, "issuer")) { |
109 | 0 | use_issuer = kOn; |
110 | 0 | if (cnf->value && !strcmp(cnf->value, "always")) { |
111 | 0 | use_issuer = kAlways; |
112 | 0 | } |
113 | 0 | } else { |
114 | 0 | OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_OPTION); |
115 | 0 | ERR_add_error_data(2, "name=", cnf->name); |
116 | 0 | return nullptr; |
117 | 0 | } |
118 | 0 | } |
119 | | |
120 | 0 | if (!ctx || !ctx->issuer_cert) { |
121 | 0 | if (ctx && (ctx->flags == X509V3_CTX_TEST)) { |
122 | 0 | return AUTHORITY_KEYID_new(); |
123 | 0 | } |
124 | 0 | OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_ISSUER_CERTIFICATE); |
125 | 0 | return nullptr; |
126 | 0 | } |
127 | | |
128 | 0 | UniquePtr<ASN1_OCTET_STRING> key_id; |
129 | 0 | if (use_key_id != kOff) { |
130 | 0 | int critical; |
131 | 0 | key_id.reset(static_cast<ASN1_OCTET_STRING *>(X509_get_ext_d2i( |
132 | 0 | ctx->issuer_cert, NID_subject_key_identifier, &critical, nullptr))); |
133 | 0 | if (key_id == nullptr && critical != -1) { |
134 | 0 | return nullptr; // Syntax error in the extension. |
135 | 0 | } |
136 | 0 | if (use_key_id == kAlways && key_id == nullptr) { |
137 | 0 | OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNABLE_TO_GET_ISSUER_KEYID); |
138 | 0 | return nullptr; |
139 | 0 | } |
140 | 0 | } |
141 | | |
142 | 0 | UniquePtr<ASN1_INTEGER> serial; |
143 | 0 | UniquePtr<GENERAL_NAMES> issuer_gens; |
144 | 0 | if ((use_issuer == kOn && key_id == nullptr) || use_issuer == kAlways) { |
145 | 0 | UniquePtr<X509_NAME> issuer_name( |
146 | 0 | X509_NAME_dup(X509_get_issuer_name(ctx->issuer_cert))); |
147 | 0 | serial.reset(ASN1_INTEGER_dup(X509_get0_serialNumber(ctx->issuer_cert))); |
148 | 0 | if (issuer_name == nullptr || serial == nullptr) { |
149 | 0 | OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS); |
150 | 0 | return nullptr; |
151 | 0 | } |
152 | | // AKID wraps the issuer name in a GeneralNames structure. |
153 | 0 | UniquePtr<GENERAL_NAME> gen(GENERAL_NAME_new()); |
154 | 0 | if (gen == nullptr) { |
155 | 0 | return nullptr; |
156 | 0 | } |
157 | 0 | gen->type = GEN_DIRNAME; |
158 | 0 | gen->d.directoryName = issuer_name.release(); |
159 | 0 | issuer_gens.reset(sk_GENERAL_NAME_new_null()); |
160 | 0 | if (issuer_gens == nullptr || |
161 | 0 | !PushToStack(issuer_gens.get(), std::move(gen))) { |
162 | 0 | return nullptr; |
163 | 0 | } |
164 | 0 | } |
165 | | |
166 | 0 | UniquePtr<AUTHORITY_KEYID> akid(AUTHORITY_KEYID_new()); |
167 | 0 | if (akid == nullptr) { |
168 | 0 | return nullptr; |
169 | 0 | } |
170 | 0 | akid->issuer = issuer_gens.release(); |
171 | 0 | akid->serial = serial.release(); |
172 | 0 | akid->keyid = key_id.release(); |
173 | 0 | return akid.release(); |
174 | 0 | } |