| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* X.509 certificate parser |
|---|
| 2 | 3 | * |
|---|
| 3 | 4 | * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. |
|---|
| 4 | 5 | * Written by David Howells (dhowells@redhat.com) |
|---|
| 5 | | - * |
|---|
| 6 | | - * This program is free software; you can redistribute it and/or |
|---|
| 7 | | - * modify it under the terms of the GNU General Public Licence |
|---|
| 8 | | - * as published by the Free Software Foundation; either version |
|---|
| 9 | | - * 2 of the Licence, or (at your option) any later version. |
|---|
| 10 | 6 | */ |
|---|
| 11 | 7 | |
|---|
| 12 | 8 | #define pr_fmt(fmt) "X.509: "fmt |
|---|
| .. | .. |
|---|
| 26 | 22 | const void *cert_start; /* Start of cert content */ |
|---|
| 27 | 23 | const void *key; /* Key data */ |
|---|
| 28 | 24 | size_t key_size; /* Size of key data */ |
|---|
| 25 | + const void *params; /* Key parameters */ |
|---|
| 26 | + size_t params_size; /* Size of key parameters */ |
|---|
| 27 | + enum OID key_algo; /* Public key algorithm */ |
|---|
| 29 | 28 | enum OID last_oid; /* Last OID encountered */ |
|---|
| 30 | 29 | enum OID algo_oid; /* Algorithm OID */ |
|---|
| 31 | 30 | unsigned char nr_mpi; /* Number of MPIs stored */ |
|---|
| .. | .. |
|---|
| 108 | 107 | goto error_decode; |
|---|
| 109 | 108 | |
|---|
| 110 | 109 | cert->pub->keylen = ctx->key_size; |
|---|
| 110 | + |
|---|
| 111 | + cert->pub->params = kmemdup(ctx->params, ctx->params_size, GFP_KERNEL); |
|---|
| 112 | + if (!cert->pub->params) |
|---|
| 113 | + goto error_decode; |
|---|
| 114 | + |
|---|
| 115 | + cert->pub->paramlen = ctx->params_size; |
|---|
| 116 | + cert->pub->algo = ctx->key_algo; |
|---|
| 111 | 117 | |
|---|
| 112 | 118 | /* Grab the signature bits */ |
|---|
| 113 | 119 | ret = x509_get_sig_params(cert); |
|---|
| .. | .. |
|---|
| 199 | 205 | |
|---|
| 200 | 206 | case OID_md4WithRSAEncryption: |
|---|
| 201 | 207 | ctx->cert->sig->hash_algo = "md4"; |
|---|
| 202 | | - ctx->cert->sig->pkey_algo = "rsa"; |
|---|
| 203 | | - break; |
|---|
| 208 | + goto rsa_pkcs1; |
|---|
| 204 | 209 | |
|---|
| 205 | 210 | case OID_sha1WithRSAEncryption: |
|---|
| 206 | 211 | ctx->cert->sig->hash_algo = "sha1"; |
|---|
| 207 | | - ctx->cert->sig->pkey_algo = "rsa"; |
|---|
| 208 | | - break; |
|---|
| 212 | + goto rsa_pkcs1; |
|---|
| 209 | 213 | |
|---|
| 210 | 214 | case OID_sha256WithRSAEncryption: |
|---|
| 211 | 215 | ctx->cert->sig->hash_algo = "sha256"; |
|---|
| 212 | | - ctx->cert->sig->pkey_algo = "rsa"; |
|---|
| 213 | | - break; |
|---|
| 216 | + goto rsa_pkcs1; |
|---|
| 214 | 217 | |
|---|
| 215 | 218 | case OID_sha384WithRSAEncryption: |
|---|
| 216 | 219 | ctx->cert->sig->hash_algo = "sha384"; |
|---|
| 217 | | - ctx->cert->sig->pkey_algo = "rsa"; |
|---|
| 218 | | - break; |
|---|
| 220 | + goto rsa_pkcs1; |
|---|
| 219 | 221 | |
|---|
| 220 | 222 | case OID_sha512WithRSAEncryption: |
|---|
| 221 | 223 | ctx->cert->sig->hash_algo = "sha512"; |
|---|
| 222 | | - ctx->cert->sig->pkey_algo = "rsa"; |
|---|
| 223 | | - break; |
|---|
| 224 | + goto rsa_pkcs1; |
|---|
| 224 | 225 | |
|---|
| 225 | 226 | case OID_sha224WithRSAEncryption: |
|---|
| 226 | 227 | ctx->cert->sig->hash_algo = "sha224"; |
|---|
| 227 | | - ctx->cert->sig->pkey_algo = "rsa"; |
|---|
| 228 | | - break; |
|---|
| 228 | + goto rsa_pkcs1; |
|---|
| 229 | + |
|---|
| 230 | + case OID_gost2012Signature256: |
|---|
| 231 | + ctx->cert->sig->hash_algo = "streebog256"; |
|---|
| 232 | + goto ecrdsa; |
|---|
| 233 | + |
|---|
| 234 | + case OID_gost2012Signature512: |
|---|
| 235 | + ctx->cert->sig->hash_algo = "streebog512"; |
|---|
| 236 | + goto ecrdsa; |
|---|
| 237 | + |
|---|
| 238 | + case OID_SM2_with_SM3: |
|---|
| 239 | + ctx->cert->sig->hash_algo = "sm3"; |
|---|
| 240 | + goto sm2; |
|---|
| 229 | 241 | } |
|---|
| 230 | 242 | |
|---|
| 243 | +rsa_pkcs1: |
|---|
| 244 | + ctx->cert->sig->pkey_algo = "rsa"; |
|---|
| 245 | + ctx->cert->sig->encoding = "pkcs1"; |
|---|
| 246 | + ctx->algo_oid = ctx->last_oid; |
|---|
| 247 | + return 0; |
|---|
| 248 | +ecrdsa: |
|---|
| 249 | + ctx->cert->sig->pkey_algo = "ecrdsa"; |
|---|
| 250 | + ctx->cert->sig->encoding = "raw"; |
|---|
| 251 | + ctx->algo_oid = ctx->last_oid; |
|---|
| 252 | + return 0; |
|---|
| 253 | +sm2: |
|---|
| 254 | + ctx->cert->sig->pkey_algo = "sm2"; |
|---|
| 255 | + ctx->cert->sig->encoding = "raw"; |
|---|
| 231 | 256 | ctx->algo_oid = ctx->last_oid; |
|---|
| 232 | 257 | return 0; |
|---|
| 233 | 258 | } |
|---|
| .. | .. |
|---|
| 249 | 274 | return -EINVAL; |
|---|
| 250 | 275 | } |
|---|
| 251 | 276 | |
|---|
| 252 | | - if (strcmp(ctx->cert->sig->pkey_algo, "rsa") == 0) { |
|---|
| 277 | + if (strcmp(ctx->cert->sig->pkey_algo, "rsa") == 0 || |
|---|
| 278 | + strcmp(ctx->cert->sig->pkey_algo, "ecrdsa") == 0 || |
|---|
| 279 | + strcmp(ctx->cert->sig->pkey_algo, "sm2") == 0) { |
|---|
| 253 | 280 | /* Discard the BIT STRING metadata */ |
|---|
| 254 | 281 | if (vlen < 1 || *(const u8 *)value != 0) |
|---|
| 255 | 282 | return -EBADMSG; |
|---|
| .. | .. |
|---|
| 404 | 431 | } |
|---|
| 405 | 432 | |
|---|
| 406 | 433 | /* |
|---|
| 434 | + * Extract the parameters for the public key |
|---|
| 435 | + */ |
|---|
| 436 | +int x509_note_params(void *context, size_t hdrlen, |
|---|
| 437 | + unsigned char tag, |
|---|
| 438 | + const void *value, size_t vlen) |
|---|
| 439 | +{ |
|---|
| 440 | + struct x509_parse_context *ctx = context; |
|---|
| 441 | + |
|---|
| 442 | + /* |
|---|
| 443 | + * AlgorithmIdentifier is used three times in the x509, we should skip |
|---|
| 444 | + * first and ignore third, using second one which is after subject and |
|---|
| 445 | + * before subjectPublicKey. |
|---|
| 446 | + */ |
|---|
| 447 | + if (!ctx->cert->raw_subject || ctx->key) |
|---|
| 448 | + return 0; |
|---|
| 449 | + ctx->params = value - hdrlen; |
|---|
| 450 | + ctx->params_size = vlen + hdrlen; |
|---|
| 451 | + return 0; |
|---|
| 452 | +} |
|---|
| 453 | + |
|---|
| 454 | +/* |
|---|
| 407 | 455 | * Extract the data for the public key algorithm |
|---|
| 408 | 456 | */ |
|---|
| 409 | 457 | int x509_extract_key_data(void *context, size_t hdrlen, |
|---|
| .. | .. |
|---|
| 412 | 460 | { |
|---|
| 413 | 461 | struct x509_parse_context *ctx = context; |
|---|
| 414 | 462 | |
|---|
| 415 | | - if (ctx->last_oid != OID_rsaEncryption) |
|---|
| 463 | + ctx->key_algo = ctx->last_oid; |
|---|
| 464 | + switch (ctx->last_oid) { |
|---|
| 465 | + case OID_rsaEncryption: |
|---|
| 466 | + ctx->cert->pub->pkey_algo = "rsa"; |
|---|
| 467 | + break; |
|---|
| 468 | + case OID_gost2012PKey256: |
|---|
| 469 | + case OID_gost2012PKey512: |
|---|
| 470 | + ctx->cert->pub->pkey_algo = "ecrdsa"; |
|---|
| 471 | + break; |
|---|
| 472 | + case OID_id_ecPublicKey: |
|---|
| 473 | + ctx->cert->pub->pkey_algo = "sm2"; |
|---|
| 474 | + break; |
|---|
| 475 | + default: |
|---|
| 416 | 476 | return -ENOPKG; |
|---|
| 417 | | - |
|---|
| 418 | | - ctx->cert->pub->pkey_algo = "rsa"; |
|---|
| 477 | + } |
|---|
| 419 | 478 | |
|---|
| 420 | 479 | /* Discard the BIT STRING metadata */ |
|---|
| 421 | 480 | if (vlen < 1 || *(const u8 *)value != 0) |
|---|