Commit | Line | Data |
---|---|---|
b4d0d230 | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
c26fd69f DH |
2 | /* X.509 certificate parser |
3 | * | |
4 | * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. | |
5 | * Written by David Howells (dhowells@redhat.com) | |
c26fd69f DH |
6 | */ |
7 | ||
8 | #define pr_fmt(fmt) "X.509: "fmt | |
9 | #include <linux/kernel.h> | |
ace0107a | 10 | #include <linux/export.h> |
c26fd69f DH |
11 | #include <linux/slab.h> |
12 | #include <linux/err.h> | |
13 | #include <linux/oid_registry.h> | |
db6c43bd | 14 | #include <crypto/public_key.h> |
c26fd69f | 15 | #include "x509_parser.h" |
4fa8bc94 MY |
16 | #include "x509.asn1.h" |
17 | #include "x509_akid.asn1.h" | |
c26fd69f DH |
18 | |
19 | struct x509_parse_context { | |
20 | struct x509_certificate *cert; /* Certificate being constructed */ | |
21 | unsigned long data; /* Start of data */ | |
c26fd69f DH |
22 | const void *key; /* Key data */ |
23 | size_t key_size; /* Size of key data */ | |
f1774cb8 VC |
24 | const void *params; /* Key parameters */ |
25 | size_t params_size; /* Size of key parameters */ | |
8f2a7b51 | 26 | enum OID key_algo; /* Algorithm used by the cert's key */ |
c26fd69f | 27 | enum OID last_oid; /* Last OID encountered */ |
8f2a7b51 | 28 | enum OID sig_algo; /* Algorithm used to sign the cert */ |
c26fd69f DH |
29 | u8 o_size; /* Size of organizationName (O) */ |
30 | u8 cn_size; /* Size of commonName (CN) */ | |
31 | u8 email_size; /* Size of emailAddress */ | |
32 | u16 o_offset; /* Offset of organizationName (O) */ | |
33 | u16 cn_offset; /* Offset of commonName (CN) */ | |
34 | u16 email_offset; /* Offset of emailAddress */ | |
b92e6570 DH |
35 | unsigned raw_akid_size; |
36 | const void *raw_akid; /* Raw authorityKeyId in ASN.1 */ | |
37 | const void *akid_raw_issuer; /* Raw directoryName in authorityKeyId */ | |
38 | unsigned akid_raw_issuer_size; | |
c26fd69f DH |
39 | }; |
40 | ||
41 | /* | |
42 | * Free an X.509 certificate | |
43 | */ | |
44 | void x509_free_certificate(struct x509_certificate *cert) | |
45 | { | |
46 | if (cert) { | |
3b764563 | 47 | public_key_free(cert->pub); |
77d0910d | 48 | public_key_signature_free(cert->sig); |
c26fd69f DH |
49 | kfree(cert->issuer); |
50 | kfree(cert->subject); | |
46963b77 DH |
51 | kfree(cert->id); |
52 | kfree(cert->skid); | |
c26fd69f DH |
53 | kfree(cert); |
54 | } | |
55 | } | |
ace0107a | 56 | EXPORT_SYMBOL_GPL(x509_free_certificate); |
c26fd69f DH |
57 | |
58 | /* | |
59 | * Parse an X.509 certificate | |
60 | */ | |
61 | struct x509_certificate *x509_cert_parse(const void *data, size_t datalen) | |
62 | { | |
5c6ca9d9 LW |
63 | struct x509_certificate *cert __free(x509_free_certificate); |
64 | struct x509_parse_context *ctx __free(kfree) = NULL; | |
46963b77 | 65 | struct asymmetric_key_id *kid; |
c26fd69f DH |
66 | long ret; |
67 | ||
c26fd69f DH |
68 | cert = kzalloc(sizeof(struct x509_certificate), GFP_KERNEL); |
69 | if (!cert) | |
5c6ca9d9 | 70 | return ERR_PTR(-ENOMEM); |
c26fd69f DH |
71 | cert->pub = kzalloc(sizeof(struct public_key), GFP_KERNEL); |
72 | if (!cert->pub) | |
5c6ca9d9 | 73 | return ERR_PTR(-ENOMEM); |
77d0910d DH |
74 | cert->sig = kzalloc(sizeof(struct public_key_signature), GFP_KERNEL); |
75 | if (!cert->sig) | |
5c6ca9d9 | 76 | return ERR_PTR(-ENOMEM); |
c26fd69f DH |
77 | ctx = kzalloc(sizeof(struct x509_parse_context), GFP_KERNEL); |
78 | if (!ctx) | |
5c6ca9d9 | 79 | return ERR_PTR(-ENOMEM); |
c26fd69f DH |
80 | |
81 | ctx->cert = cert; | |
82 | ctx->data = (unsigned long)data; | |
83 | ||
84 | /* Attempt to decode the certificate */ | |
85 | ret = asn1_ber_decoder(&x509_decoder, ctx, data, datalen); | |
86 | if (ret < 0) | |
5c6ca9d9 | 87 | return ERR_PTR(ret); |
c26fd69f | 88 | |
b92e6570 DH |
89 | /* Decode the AuthorityKeyIdentifier */ |
90 | if (ctx->raw_akid) { | |
91 | pr_devel("AKID: %u %*phN\n", | |
92 | ctx->raw_akid_size, ctx->raw_akid_size, ctx->raw_akid); | |
93 | ret = asn1_ber_decoder(&x509_akid_decoder, ctx, | |
94 | ctx->raw_akid, ctx->raw_akid_size); | |
95 | if (ret < 0) { | |
96 | pr_warn("Couldn't decode AuthKeyIdentifier\n"); | |
5c6ca9d9 | 97 | return ERR_PTR(ret); |
b92e6570 DH |
98 | } |
99 | } | |
100 | ||
db6c43bd TS |
101 | cert->pub->key = kmemdup(ctx->key, ctx->key_size, GFP_KERNEL); |
102 | if (!cert->pub->key) | |
5c6ca9d9 | 103 | return ERR_PTR(-ENOMEM); |
c26fd69f | 104 | |
db6c43bd TS |
105 | cert->pub->keylen = ctx->key_size; |
106 | ||
f1774cb8 VC |
107 | cert->pub->params = kmemdup(ctx->params, ctx->params_size, GFP_KERNEL); |
108 | if (!cert->pub->params) | |
5c6ca9d9 | 109 | return ERR_PTR(-ENOMEM); |
f1774cb8 VC |
110 | |
111 | cert->pub->paramlen = ctx->params_size; | |
112 | cert->pub->algo = ctx->key_algo; | |
113 | ||
6c2dc5ae DH |
114 | /* Grab the signature bits */ |
115 | ret = x509_get_sig_params(cert); | |
116 | if (ret < 0) | |
5c6ca9d9 | 117 | return ERR_PTR(ret); |
6c2dc5ae | 118 | |
46963b77 DH |
119 | /* Generate cert issuer + serial number key ID */ |
120 | kid = asymmetric_key_generate_id(cert->raw_serial, | |
121 | cert->raw_serial_size, | |
122 | cert->raw_issuer, | |
123 | cert->raw_issuer_size); | |
5c6ca9d9 LW |
124 | if (IS_ERR(kid)) |
125 | return ERR_CAST(kid); | |
46963b77 DH |
126 | cert->id = kid; |
127 | ||
6c2dc5ae DH |
128 | /* Detect self-signed certificates */ |
129 | ret = x509_check_for_self_signed(cert); | |
130 | if (ret < 0) | |
5c6ca9d9 | 131 | return ERR_PTR(ret); |
c26fd69f | 132 | |
5c6ca9d9 | 133 | return_ptr(cert); |
c26fd69f | 134 | } |
ace0107a | 135 | EXPORT_SYMBOL_GPL(x509_cert_parse); |
c26fd69f DH |
136 | |
137 | /* | |
138 | * Note an OID when we find one for later processing when we know how | |
139 | * to interpret it. | |
140 | */ | |
141 | int x509_note_OID(void *context, size_t hdrlen, | |
142 | unsigned char tag, | |
143 | const void *value, size_t vlen) | |
144 | { | |
145 | struct x509_parse_context *ctx = context; | |
146 | ||
147 | ctx->last_oid = look_up_OID(value, vlen); | |
148 | if (ctx->last_oid == OID__NR) { | |
149 | char buffer[50]; | |
150 | sprint_oid(value, vlen, buffer, sizeof(buffer)); | |
cf75446e | 151 | pr_debug("Unknown OID: [%lu] %s\n", |
c26fd69f DH |
152 | (unsigned long)value - ctx->data, buffer); |
153 | } | |
154 | return 0; | |
155 | } | |
156 | ||
157 | /* | |
158 | * Save the position of the TBS data so that we can check the signature over it | |
159 | * later. | |
160 | */ | |
161 | int x509_note_tbs_certificate(void *context, size_t hdrlen, | |
162 | unsigned char tag, | |
163 | const void *value, size_t vlen) | |
164 | { | |
165 | struct x509_parse_context *ctx = context; | |
166 | ||
167 | pr_debug("x509_note_tbs_certificate(,%zu,%02x,%ld,%zu)!\n", | |
168 | hdrlen, tag, (unsigned long)value - ctx->data, vlen); | |
169 | ||
170 | ctx->cert->tbs = value - hdrlen; | |
171 | ctx->cert->tbs_size = vlen + hdrlen; | |
172 | return 0; | |
173 | } | |
174 | ||
175 | /* | |
8f2a7b51 | 176 | * Record the algorithm that was used to sign this certificate. |
c26fd69f | 177 | */ |
8f2a7b51 EB |
178 | int x509_note_sig_algo(void *context, size_t hdrlen, unsigned char tag, |
179 | const void *value, size_t vlen) | |
c26fd69f DH |
180 | { |
181 | struct x509_parse_context *ctx = context; | |
182 | ||
183 | pr_debug("PubKey Algo: %u\n", ctx->last_oid); | |
184 | ||
185 | switch (ctx->last_oid) { | |
c26fd69f DH |
186 | default: |
187 | return -ENOPKG; /* Unsupported combination */ | |
188 | ||
203a6763 EB |
189 | case OID_sha1WithRSAEncryption: |
190 | ctx->cert->sig->hash_algo = "sha1"; | |
191 | goto rsa_pkcs1; | |
192 | ||
c26fd69f | 193 | case OID_sha256WithRSAEncryption: |
77d0910d | 194 | ctx->cert->sig->hash_algo = "sha256"; |
03988490 | 195 | goto rsa_pkcs1; |
c26fd69f DH |
196 | |
197 | case OID_sha384WithRSAEncryption: | |
77d0910d | 198 | ctx->cert->sig->hash_algo = "sha384"; |
03988490 | 199 | goto rsa_pkcs1; |
c26fd69f DH |
200 | |
201 | case OID_sha512WithRSAEncryption: | |
77d0910d | 202 | ctx->cert->sig->hash_algo = "sha512"; |
03988490 | 203 | goto rsa_pkcs1; |
c26fd69f DH |
204 | |
205 | case OID_sha224WithRSAEncryption: | |
77d0910d | 206 | ctx->cert->sig->hash_algo = "sha224"; |
03988490 | 207 | goto rsa_pkcs1; |
0d7a7864 | 208 | |
203a6763 EB |
209 | case OID_id_ecdsa_with_sha1: |
210 | ctx->cert->sig->hash_algo = "sha1"; | |
211 | goto ecdsa; | |
212 | ||
fdb4f66c DJL |
213 | case OID_id_rsassa_pkcs1_v1_5_with_sha3_256: |
214 | ctx->cert->sig->hash_algo = "sha3-256"; | |
215 | goto rsa_pkcs1; | |
216 | ||
217 | case OID_id_rsassa_pkcs1_v1_5_with_sha3_384: | |
218 | ctx->cert->sig->hash_algo = "sha3-384"; | |
219 | goto rsa_pkcs1; | |
220 | ||
221 | case OID_id_rsassa_pkcs1_v1_5_with_sha3_512: | |
222 | ctx->cert->sig->hash_algo = "sha3-512"; | |
223 | goto rsa_pkcs1; | |
224 | ||
299f561a SB |
225 | case OID_id_ecdsa_with_sha224: |
226 | ctx->cert->sig->hash_algo = "sha224"; | |
227 | goto ecdsa; | |
228 | ||
229 | case OID_id_ecdsa_with_sha256: | |
230 | ctx->cert->sig->hash_algo = "sha256"; | |
231 | goto ecdsa; | |
232 | ||
233 | case OID_id_ecdsa_with_sha384: | |
234 | ctx->cert->sig->hash_algo = "sha384"; | |
235 | goto ecdsa; | |
236 | ||
237 | case OID_id_ecdsa_with_sha512: | |
238 | ctx->cert->sig->hash_algo = "sha512"; | |
239 | goto ecdsa; | |
240 | ||
fdb4f66c DJL |
241 | case OID_id_ecdsa_with_sha3_256: |
242 | ctx->cert->sig->hash_algo = "sha3-256"; | |
243 | goto ecdsa; | |
244 | ||
245 | case OID_id_ecdsa_with_sha3_384: | |
246 | ctx->cert->sig->hash_algo = "sha3-384"; | |
247 | goto ecdsa; | |
248 | ||
249 | case OID_id_ecdsa_with_sha3_512: | |
250 | ctx->cert->sig->hash_algo = "sha3-512"; | |
251 | goto ecdsa; | |
252 | ||
0d7a7864 VC |
253 | case OID_gost2012Signature256: |
254 | ctx->cert->sig->hash_algo = "streebog256"; | |
255 | goto ecrdsa; | |
256 | ||
257 | case OID_gost2012Signature512: | |
258 | ctx->cert->sig->hash_algo = "streebog512"; | |
259 | goto ecrdsa; | |
254f84f5 TZ |
260 | |
261 | case OID_SM2_with_SM3: | |
262 | ctx->cert->sig->hash_algo = "sm3"; | |
263 | goto sm2; | |
c26fd69f DH |
264 | } |
265 | ||
03988490 DH |
266 | rsa_pkcs1: |
267 | ctx->cert->sig->pkey_algo = "rsa"; | |
268 | ctx->cert->sig->encoding = "pkcs1"; | |
8f2a7b51 | 269 | ctx->sig_algo = ctx->last_oid; |
c26fd69f | 270 | return 0; |
0d7a7864 VC |
271 | ecrdsa: |
272 | ctx->cert->sig->pkey_algo = "ecrdsa"; | |
273 | ctx->cert->sig->encoding = "raw"; | |
8f2a7b51 | 274 | ctx->sig_algo = ctx->last_oid; |
0d7a7864 | 275 | return 0; |
254f84f5 TZ |
276 | sm2: |
277 | ctx->cert->sig->pkey_algo = "sm2"; | |
278 | ctx->cert->sig->encoding = "raw"; | |
8f2a7b51 | 279 | ctx->sig_algo = ctx->last_oid; |
254f84f5 | 280 | return 0; |
299f561a SB |
281 | ecdsa: |
282 | ctx->cert->sig->pkey_algo = "ecdsa"; | |
283 | ctx->cert->sig->encoding = "x962"; | |
8f2a7b51 | 284 | ctx->sig_algo = ctx->last_oid; |
299f561a | 285 | return 0; |
c26fd69f DH |
286 | } |
287 | ||
288 | /* | |
289 | * Note the whereabouts and type of the signature. | |
290 | */ | |
291 | int x509_note_signature(void *context, size_t hdrlen, | |
292 | unsigned char tag, | |
293 | const void *value, size_t vlen) | |
294 | { | |
295 | struct x509_parse_context *ctx = context; | |
296 | ||
8f2a7b51 | 297 | pr_debug("Signature: alg=%u, size=%zu\n", ctx->last_oid, vlen); |
c26fd69f | 298 | |
8f2a7b51 EB |
299 | /* |
300 | * In X.509 certificates, the signature's algorithm is stored in two | |
301 | * places: inside the TBSCertificate (the data that is signed), and | |
302 | * alongside the signature. These *must* match. | |
303 | */ | |
304 | if (ctx->last_oid != ctx->sig_algo) { | |
305 | pr_warn("signatureAlgorithm (%u) differs from tbsCertificate.signature (%u)\n", | |
306 | ctx->last_oid, ctx->sig_algo); | |
c26fd69f DH |
307 | return -EINVAL; |
308 | } | |
309 | ||
0d7a7864 | 310 | if (strcmp(ctx->cert->sig->pkey_algo, "rsa") == 0 || |
254f84f5 | 311 | strcmp(ctx->cert->sig->pkey_algo, "ecrdsa") == 0 || |
299f561a SB |
312 | strcmp(ctx->cert->sig->pkey_algo, "sm2") == 0 || |
313 | strcmp(ctx->cert->sig->pkey_algo, "ecdsa") == 0) { | |
b65c32ec MS |
314 | /* Discard the BIT STRING metadata */ |
315 | if (vlen < 1 || *(const u8 *)value != 0) | |
316 | return -EBADMSG; | |
317 | ||
318 | value++; | |
319 | vlen--; | |
320 | } | |
321 | ||
b426beb6 DH |
322 | ctx->cert->raw_sig = value; |
323 | ctx->cert->raw_sig_size = vlen; | |
c26fd69f DH |
324 | return 0; |
325 | } | |
326 | ||
84aabd46 DH |
327 | /* |
328 | * Note the certificate serial number | |
329 | */ | |
330 | int x509_note_serial(void *context, size_t hdrlen, | |
331 | unsigned char tag, | |
332 | const void *value, size_t vlen) | |
333 | { | |
334 | struct x509_parse_context *ctx = context; | |
335 | ctx->cert->raw_serial = value; | |
336 | ctx->cert->raw_serial_size = vlen; | |
337 | return 0; | |
338 | } | |
339 | ||
c26fd69f DH |
340 | /* |
341 | * Note some of the name segments from which we'll fabricate a name. | |
342 | */ | |
343 | int x509_extract_name_segment(void *context, size_t hdrlen, | |
344 | unsigned char tag, | |
345 | const void *value, size_t vlen) | |
346 | { | |
347 | struct x509_parse_context *ctx = context; | |
348 | ||
349 | switch (ctx->last_oid) { | |
350 | case OID_commonName: | |
351 | ctx->cn_size = vlen; | |
352 | ctx->cn_offset = (unsigned long)value - ctx->data; | |
353 | break; | |
354 | case OID_organizationName: | |
355 | ctx->o_size = vlen; | |
356 | ctx->o_offset = (unsigned long)value - ctx->data; | |
357 | break; | |
358 | case OID_email_address: | |
359 | ctx->email_size = vlen; | |
360 | ctx->email_offset = (unsigned long)value - ctx->data; | |
361 | break; | |
362 | default: | |
363 | break; | |
364 | } | |
365 | ||
366 | return 0; | |
367 | } | |
368 | ||
369 | /* | |
370 | * Fabricate and save the issuer and subject names | |
371 | */ | |
372 | static int x509_fabricate_name(struct x509_parse_context *ctx, size_t hdrlen, | |
373 | unsigned char tag, | |
374 | char **_name, size_t vlen) | |
375 | { | |
376 | const void *name, *data = (const void *)ctx->data; | |
377 | size_t namesize; | |
378 | char *buffer; | |
379 | ||
380 | if (*_name) | |
381 | return -EINVAL; | |
382 | ||
383 | /* Empty name string if no material */ | |
384 | if (!ctx->cn_size && !ctx->o_size && !ctx->email_size) { | |
385 | buffer = kmalloc(1, GFP_KERNEL); | |
386 | if (!buffer) | |
387 | return -ENOMEM; | |
388 | buffer[0] = 0; | |
389 | goto done; | |
390 | } | |
391 | ||
392 | if (ctx->cn_size && ctx->o_size) { | |
393 | /* Consider combining O and CN, but use only the CN if it is | |
394 | * prefixed by the O, or a significant portion thereof. | |
395 | */ | |
396 | namesize = ctx->cn_size; | |
397 | name = data + ctx->cn_offset; | |
398 | if (ctx->cn_size >= ctx->o_size && | |
399 | memcmp(data + ctx->cn_offset, data + ctx->o_offset, | |
400 | ctx->o_size) == 0) | |
401 | goto single_component; | |
402 | if (ctx->cn_size >= 7 && | |
403 | ctx->o_size >= 7 && | |
404 | memcmp(data + ctx->cn_offset, data + ctx->o_offset, 7) == 0) | |
405 | goto single_component; | |
406 | ||
407 | buffer = kmalloc(ctx->o_size + 2 + ctx->cn_size + 1, | |
408 | GFP_KERNEL); | |
409 | if (!buffer) | |
410 | return -ENOMEM; | |
411 | ||
412 | memcpy(buffer, | |
413 | data + ctx->o_offset, ctx->o_size); | |
414 | buffer[ctx->o_size + 0] = ':'; | |
415 | buffer[ctx->o_size + 1] = ' '; | |
416 | memcpy(buffer + ctx->o_size + 2, | |
417 | data + ctx->cn_offset, ctx->cn_size); | |
418 | buffer[ctx->o_size + 2 + ctx->cn_size] = 0; | |
419 | goto done; | |
420 | ||
421 | } else if (ctx->cn_size) { | |
422 | namesize = ctx->cn_size; | |
423 | name = data + ctx->cn_offset; | |
424 | } else if (ctx->o_size) { | |
425 | namesize = ctx->o_size; | |
426 | name = data + ctx->o_offset; | |
427 | } else { | |
428 | namesize = ctx->email_size; | |
429 | name = data + ctx->email_offset; | |
430 | } | |
431 | ||
432 | single_component: | |
433 | buffer = kmalloc(namesize + 1, GFP_KERNEL); | |
434 | if (!buffer) | |
435 | return -ENOMEM; | |
436 | memcpy(buffer, name, namesize); | |
437 | buffer[namesize] = 0; | |
438 | ||
439 | done: | |
440 | *_name = buffer; | |
441 | ctx->cn_size = 0; | |
442 | ctx->o_size = 0; | |
443 | ctx->email_size = 0; | |
444 | return 0; | |
445 | } | |
446 | ||
447 | int x509_note_issuer(void *context, size_t hdrlen, | |
448 | unsigned char tag, | |
449 | const void *value, size_t vlen) | |
450 | { | |
451 | struct x509_parse_context *ctx = context; | |
7d30198e AZ |
452 | struct asymmetric_key_id *kid; |
453 | ||
84aabd46 DH |
454 | ctx->cert->raw_issuer = value; |
455 | ctx->cert->raw_issuer_size = vlen; | |
7d30198e AZ |
456 | |
457 | if (!ctx->cert->sig->auth_ids[2]) { | |
458 | kid = asymmetric_key_generate_id(value, vlen, "", 0); | |
459 | if (IS_ERR(kid)) | |
460 | return PTR_ERR(kid); | |
461 | ctx->cert->sig->auth_ids[2] = kid; | |
462 | } | |
463 | ||
c26fd69f DH |
464 | return x509_fabricate_name(ctx, hdrlen, tag, &ctx->cert->issuer, vlen); |
465 | } | |
466 | ||
467 | int x509_note_subject(void *context, size_t hdrlen, | |
468 | unsigned char tag, | |
469 | const void *value, size_t vlen) | |
470 | { | |
471 | struct x509_parse_context *ctx = context; | |
84aabd46 DH |
472 | ctx->cert->raw_subject = value; |
473 | ctx->cert->raw_subject_size = vlen; | |
c26fd69f DH |
474 | return x509_fabricate_name(ctx, hdrlen, tag, &ctx->cert->subject, vlen); |
475 | } | |
476 | ||
f1774cb8 VC |
477 | /* |
478 | * Extract the parameters for the public key | |
479 | */ | |
480 | int x509_note_params(void *context, size_t hdrlen, | |
481 | unsigned char tag, | |
482 | const void *value, size_t vlen) | |
483 | { | |
484 | struct x509_parse_context *ctx = context; | |
485 | ||
486 | /* | |
487 | * AlgorithmIdentifier is used three times in the x509, we should skip | |
488 | * first and ignore third, using second one which is after subject and | |
489 | * before subjectPublicKey. | |
490 | */ | |
491 | if (!ctx->cert->raw_subject || ctx->key) | |
492 | return 0; | |
493 | ctx->params = value - hdrlen; | |
494 | ctx->params_size = vlen + hdrlen; | |
495 | return 0; | |
496 | } | |
497 | ||
c26fd69f DH |
498 | /* |
499 | * Extract the data for the public key algorithm | |
500 | */ | |
501 | int x509_extract_key_data(void *context, size_t hdrlen, | |
502 | unsigned char tag, | |
503 | const void *value, size_t vlen) | |
504 | { | |
505 | struct x509_parse_context *ctx = context; | |
d1a303e8 | 506 | enum OID oid; |
c26fd69f | 507 | |
0d7a7864 | 508 | ctx->key_algo = ctx->last_oid; |
254f84f5 TZ |
509 | switch (ctx->last_oid) { |
510 | case OID_rsaEncryption: | |
0d7a7864 | 511 | ctx->cert->pub->pkey_algo = "rsa"; |
254f84f5 TZ |
512 | break; |
513 | case OID_gost2012PKey256: | |
514 | case OID_gost2012PKey512: | |
0d7a7864 | 515 | ctx->cert->pub->pkey_algo = "ecrdsa"; |
254f84f5 | 516 | break; |
74ad4334 TZ |
517 | case OID_sm2: |
518 | ctx->cert->pub->pkey_algo = "sm2"; | |
519 | break; | |
254f84f5 | 520 | case OID_id_ecPublicKey: |
d1a303e8 SB |
521 | if (parse_OID(ctx->params, ctx->params_size, &oid) != 0) |
522 | return -EBADMSG; | |
523 | ||
524 | switch (oid) { | |
525 | case OID_sm2: | |
526 | ctx->cert->pub->pkey_algo = "sm2"; | |
527 | break; | |
299f561a SB |
528 | case OID_id_prime192v1: |
529 | ctx->cert->pub->pkey_algo = "ecdsa-nist-p192"; | |
530 | break; | |
531 | case OID_id_prime256v1: | |
532 | ctx->cert->pub->pkey_algo = "ecdsa-nist-p256"; | |
533 | break; | |
2a8e6154 SA |
534 | case OID_id_ansip384r1: |
535 | ctx->cert->pub->pkey_algo = "ecdsa-nist-p384"; | |
536 | break; | |
3ba2ae36 SB |
537 | case OID_id_ansip521r1: |
538 | ctx->cert->pub->pkey_algo = "ecdsa-nist-p521"; | |
539 | break; | |
d1a303e8 SB |
540 | default: |
541 | return -ENOPKG; | |
542 | } | |
254f84f5 TZ |
543 | break; |
544 | default: | |
c26fd69f | 545 | return -ENOPKG; |
254f84f5 | 546 | } |
c26fd69f | 547 | |
67f7d60b | 548 | /* Discard the BIT STRING metadata */ |
0f30cbea EB |
549 | if (vlen < 1 || *(const u8 *)value != 0) |
550 | return -EBADMSG; | |
c26fd69f DH |
551 | ctx->key = value + 1; |
552 | ctx->key_size = vlen - 1; | |
553 | return 0; | |
554 | } | |
555 | ||
04b00bdb CYL |
556 | /* The keyIdentifier in AuthorityKeyIdentifier SEQUENCE is tag(CONT,PRIM,0) */ |
557 | #define SEQ_TAG_KEYID (ASN1_CONT << 6) | |
558 | ||
c26fd69f DH |
559 | /* |
560 | * Process certificate extensions that are used to qualify the certificate. | |
561 | */ | |
562 | int x509_process_extension(void *context, size_t hdrlen, | |
563 | unsigned char tag, | |
564 | const void *value, size_t vlen) | |
565 | { | |
566 | struct x509_parse_context *ctx = context; | |
46963b77 | 567 | struct asymmetric_key_id *kid; |
c26fd69f | 568 | const unsigned char *v = value; |
c26fd69f DH |
569 | |
570 | pr_debug("Extension: %u\n", ctx->last_oid); | |
571 | ||
572 | if (ctx->last_oid == OID_subjectKeyIdentifier) { | |
573 | /* Get hold of the key fingerprint */ | |
46963b77 | 574 | if (ctx->cert->skid || vlen < 3) |
c26fd69f DH |
575 | return -EBADMSG; |
576 | if (v[0] != ASN1_OTS || v[1] != vlen - 2) | |
577 | return -EBADMSG; | |
578 | v += 2; | |
579 | vlen -= 2; | |
580 | ||
dd2f6c44 DH |
581 | ctx->cert->raw_skid_size = vlen; |
582 | ctx->cert->raw_skid = v; | |
a4c6e57f | 583 | kid = asymmetric_key_generate_id(v, vlen, "", 0); |
46963b77 DH |
584 | if (IS_ERR(kid)) |
585 | return PTR_ERR(kid); | |
586 | ctx->cert->skid = kid; | |
587 | pr_debug("subjkeyid %*phN\n", kid->len, kid->data); | |
c26fd69f DH |
588 | return 0; |
589 | } | |
590 | ||
56767128 ES |
591 | if (ctx->last_oid == OID_keyUsage) { |
592 | /* | |
593 | * Get hold of the keyUsage bit string | |
594 | * v[1] is the encoding size | |
595 | * (Expect either 0x02 or 0x03, making it 1 or 2 bytes) | |
596 | * v[2] is the number of unused bits in the bit string | |
597 | * (If >= 3 keyCertSign is missing when v[1] = 0x02) | |
598 | * v[3] and possibly v[4] contain the bit string | |
599 | * | |
600 | * From RFC 5280 4.2.1.3: | |
601 | * 0x04 is where keyCertSign lands in this bit string | |
602 | * 0x80 is where digitalSignature lands in this bit string | |
603 | */ | |
604 | if (v[0] != ASN1_BTS) | |
605 | return -EBADMSG; | |
606 | if (vlen < 4) | |
607 | return -EBADMSG; | |
608 | if (v[2] >= 8) | |
609 | return -EBADMSG; | |
610 | if (v[3] & 0x80) | |
611 | ctx->cert->pub->key_eflags |= 1 << KEY_EFLAG_DIGITALSIG; | |
612 | if (v[1] == 0x02 && v[2] <= 2 && (v[3] & 0x04)) | |
613 | ctx->cert->pub->key_eflags |= 1 << KEY_EFLAG_KEYCERTSIGN; | |
614 | else if (vlen > 4 && v[1] == 0x03 && (v[3] & 0x04)) | |
615 | ctx->cert->pub->key_eflags |= 1 << KEY_EFLAG_KEYCERTSIGN; | |
616 | return 0; | |
617 | } | |
618 | ||
c26fd69f DH |
619 | if (ctx->last_oid == OID_authorityKeyIdentifier) { |
620 | /* Get hold of the CA key fingerprint */ | |
b92e6570 DH |
621 | ctx->raw_akid = v; |
622 | ctx->raw_akid_size = vlen; | |
c26fd69f DH |
623 | return 0; |
624 | } | |
625 | ||
30eae2b0 ES |
626 | if (ctx->last_oid == OID_basicConstraints) { |
627 | /* | |
628 | * Get hold of the basicConstraints | |
629 | * v[1] is the encoding size | |
630 | * (Expect 0x2 or greater, making it 1 or more bytes) | |
631 | * v[2] is the encoding type | |
632 | * (Expect an ASN1_BOOL for the CA) | |
633 | * v[3] is the contents of the ASN1_BOOL | |
634 | * (Expect 1 if the CA is TRUE) | |
635 | * vlen should match the entire extension size | |
636 | */ | |
637 | if (v[0] != (ASN1_CONS_BIT | ASN1_SEQ)) | |
638 | return -EBADMSG; | |
639 | if (vlen < 2) | |
640 | return -EBADMSG; | |
641 | if (v[1] != vlen - 2) | |
642 | return -EBADMSG; | |
643 | if (vlen >= 4 && v[1] != 0 && v[2] == ASN1_BOOL && v[3] == 1) | |
644 | ctx->cert->pub->key_eflags |= 1 << KEY_EFLAG_CA; | |
645 | return 0; | |
646 | } | |
647 | ||
c26fd69f DH |
648 | return 0; |
649 | } | |
650 | ||
fd19a3d1 DH |
651 | /** |
652 | * x509_decode_time - Decode an X.509 time ASN.1 object | |
653 | * @_t: The time to fill in | |
654 | * @hdrlen: The length of the object header | |
655 | * @tag: The object tag | |
656 | * @value: The object value | |
657 | * @vlen: The size of the object value | |
658 | * | |
659 | * Decode an ASN.1 universal time or generalised time field into a struct the | |
660 | * kernel can handle and check it for validity. The time is decoded thus: | |
661 | * | |
662 | * [RFC5280 ยง4.1.2.5] | |
663 | * CAs conforming to this profile MUST always encode certificate validity | |
664 | * dates through the year 2049 as UTCTime; certificate validity dates in | |
665 | * 2050 or later MUST be encoded as GeneralizedTime. Conforming | |
666 | * applications MUST be able to process validity dates that are encoded in | |
667 | * either UTCTime or GeneralizedTime. | |
c26fd69f | 668 | */ |
fd19a3d1 DH |
669 | int x509_decode_time(time64_t *_t, size_t hdrlen, |
670 | unsigned char tag, | |
671 | const unsigned char *value, size_t vlen) | |
c26fd69f | 672 | { |
ac4cbedf | 673 | static const unsigned char month_lengths[] = { 31, 28, 31, 30, 31, 30, |
fd19a3d1 | 674 | 31, 31, 30, 31, 30, 31 }; |
c26fd69f | 675 | const unsigned char *p = value; |
fd19a3d1 | 676 | unsigned year, mon, day, hour, min, sec, mon_len; |
c26fd69f | 677 | |
fd19a3d1 | 678 | #define dec2bin(X) ({ unsigned char x = (X) - '0'; if (x > 9) goto invalid_time; x; }) |
c26fd69f DH |
679 | #define DD2bin(P) ({ unsigned x = dec2bin(P[0]) * 10 + dec2bin(P[1]); P += 2; x; }) |
680 | ||
681 | if (tag == ASN1_UNITIM) { | |
682 | /* UTCTime: YYMMDDHHMMSSZ */ | |
683 | if (vlen != 13) | |
684 | goto unsupported_time; | |
fd19a3d1 DH |
685 | year = DD2bin(p); |
686 | if (year >= 50) | |
687 | year += 1900; | |
c26fd69f | 688 | else |
fd19a3d1 | 689 | year += 2000; |
c26fd69f DH |
690 | } else if (tag == ASN1_GENTIM) { |
691 | /* GenTime: YYYYMMDDHHMMSSZ */ | |
692 | if (vlen != 15) | |
693 | goto unsupported_time; | |
fd19a3d1 DH |
694 | year = DD2bin(p) * 100 + DD2bin(p); |
695 | if (year >= 1950 && year <= 2049) | |
696 | goto invalid_time; | |
c26fd69f DH |
697 | } else { |
698 | goto unsupported_time; | |
699 | } | |
700 | ||
fd19a3d1 DH |
701 | mon = DD2bin(p); |
702 | day = DD2bin(p); | |
703 | hour = DD2bin(p); | |
704 | min = DD2bin(p); | |
705 | sec = DD2bin(p); | |
c26fd69f DH |
706 | |
707 | if (*p != 'Z') | |
708 | goto unsupported_time; | |
709 | ||
cc25b994 DH |
710 | if (year < 1970 || |
711 | mon < 1 || mon > 12) | |
712 | goto invalid_time; | |
713 | ||
714 | mon_len = month_lengths[mon - 1]; | |
fd19a3d1 DH |
715 | if (mon == 2) { |
716 | if (year % 4 == 0) { | |
717 | mon_len = 29; | |
718 | if (year % 100 == 0) { | |
ac4cbedf DH |
719 | mon_len = 28; |
720 | if (year % 400 == 0) | |
721 | mon_len = 29; | |
fd19a3d1 DH |
722 | } |
723 | } | |
724 | } | |
725 | ||
cc25b994 | 726 | if (day < 1 || day > mon_len || |
7650cb80 | 727 | hour > 24 || /* ISO 8601 permits 24:00:00 as midnight tomorrow */ |
4dd17c9c | 728 | min > 59 || |
da02559c | 729 | sec > 60) /* ISO 8601 permits leap seconds [X.680 46.3] */ |
fd19a3d1 | 730 | goto invalid_time; |
cc25b994 | 731 | |
fd19a3d1 | 732 | *_t = mktime64(year, mon, day, hour, min, sec); |
c26fd69f DH |
733 | return 0; |
734 | ||
735 | unsupported_time: | |
fd19a3d1 DH |
736 | pr_debug("Got unsupported time [tag %02x]: '%*phN'\n", |
737 | tag, (int)vlen, value); | |
738 | return -EBADMSG; | |
739 | invalid_time: | |
740 | pr_debug("Got invalid time [tag %02x]: '%*phN'\n", | |
741 | tag, (int)vlen, value); | |
c26fd69f DH |
742 | return -EBADMSG; |
743 | } | |
fd19a3d1 | 744 | EXPORT_SYMBOL_GPL(x509_decode_time); |
c26fd69f DH |
745 | |
746 | int x509_note_not_before(void *context, size_t hdrlen, | |
747 | unsigned char tag, | |
748 | const void *value, size_t vlen) | |
749 | { | |
750 | struct x509_parse_context *ctx = context; | |
fd19a3d1 | 751 | return x509_decode_time(&ctx->cert->valid_from, hdrlen, tag, value, vlen); |
c26fd69f DH |
752 | } |
753 | ||
754 | int x509_note_not_after(void *context, size_t hdrlen, | |
755 | unsigned char tag, | |
756 | const void *value, size_t vlen) | |
757 | { | |
758 | struct x509_parse_context *ctx = context; | |
fd19a3d1 | 759 | return x509_decode_time(&ctx->cert->valid_to, hdrlen, tag, value, vlen); |
c26fd69f | 760 | } |
b92e6570 DH |
761 | |
762 | /* | |
763 | * Note a key identifier-based AuthorityKeyIdentifier | |
764 | */ | |
765 | int x509_akid_note_kid(void *context, size_t hdrlen, | |
766 | unsigned char tag, | |
767 | const void *value, size_t vlen) | |
768 | { | |
769 | struct x509_parse_context *ctx = context; | |
770 | struct asymmetric_key_id *kid; | |
771 | ||
772 | pr_debug("AKID: keyid: %*phN\n", (int)vlen, value); | |
773 | ||
77d0910d | 774 | if (ctx->cert->sig->auth_ids[1]) |
b92e6570 DH |
775 | return 0; |
776 | ||
a4c6e57f | 777 | kid = asymmetric_key_generate_id(value, vlen, "", 0); |
b92e6570 DH |
778 | if (IS_ERR(kid)) |
779 | return PTR_ERR(kid); | |
780 | pr_debug("authkeyid %*phN\n", kid->len, kid->data); | |
77d0910d | 781 | ctx->cert->sig->auth_ids[1] = kid; |
b92e6570 DH |
782 | return 0; |
783 | } | |
784 | ||
785 | /* | |
786 | * Note a directoryName in an AuthorityKeyIdentifier | |
787 | */ | |
788 | int x509_akid_note_name(void *context, size_t hdrlen, | |
789 | unsigned char tag, | |
790 | const void *value, size_t vlen) | |
791 | { | |
792 | struct x509_parse_context *ctx = context; | |
793 | ||
794 | pr_debug("AKID: name: %*phN\n", (int)vlen, value); | |
795 | ||
796 | ctx->akid_raw_issuer = value; | |
797 | ctx->akid_raw_issuer_size = vlen; | |
798 | return 0; | |
799 | } | |
800 | ||
801 | /* | |
802 | * Note a serial number in an AuthorityKeyIdentifier | |
803 | */ | |
804 | int x509_akid_note_serial(void *context, size_t hdrlen, | |
805 | unsigned char tag, | |
806 | const void *value, size_t vlen) | |
807 | { | |
808 | struct x509_parse_context *ctx = context; | |
809 | struct asymmetric_key_id *kid; | |
810 | ||
811 | pr_debug("AKID: serial: %*phN\n", (int)vlen, value); | |
812 | ||
77d0910d | 813 | if (!ctx->akid_raw_issuer || ctx->cert->sig->auth_ids[0]) |
b92e6570 DH |
814 | return 0; |
815 | ||
816 | kid = asymmetric_key_generate_id(value, | |
817 | vlen, | |
818 | ctx->akid_raw_issuer, | |
819 | ctx->akid_raw_issuer_size); | |
820 | if (IS_ERR(kid)) | |
821 | return PTR_ERR(kid); | |
822 | ||
823 | pr_debug("authkeyid %*phN\n", kid->len, kid->data); | |
77d0910d | 824 | ctx->cert->sig->auth_ids[0] = kid; |
b92e6570 DH |
825 | return 0; |
826 | } |