Raymond Mao | 702817b | 2024-10-03 14:50:28 -0700 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0+ |
| 2 | /* |
| 3 | * Public key helper functions using MbedTLS X509 library |
| 4 | * |
| 5 | * Copyright (c) 2024 Linaro Limited |
| 6 | * Author: Raymond Mao <raymond.mao@linaro.org> |
| 7 | */ |
| 8 | |
| 9 | #include <linux/compat.h> |
| 10 | #include <crypto/public_key.h> |
| 11 | |
| 12 | int public_key_verify_signature(const struct public_key *pkey, |
| 13 | const struct public_key_signature *sig) |
| 14 | { |
| 15 | mbedtls_md_type_t mb_hash_algo; |
| 16 | mbedtls_pk_context pk_ctx; |
| 17 | int ret; |
| 18 | |
| 19 | if (!pkey || !sig || pkey->key_is_private) |
| 20 | return -EINVAL; |
| 21 | |
| 22 | /* |
| 23 | * ECRDSA (Elliptic Curve Russian Digital Signature Algorithm) is not |
| 24 | * supported by MbedTLS. |
| 25 | */ |
| 26 | if (strcmp(pkey->pkey_algo, "rsa")) { |
| 27 | pr_err("Encryption is not RSA: %s\n", sig->pkey_algo); |
| 28 | return -EINVAL; |
| 29 | } |
| 30 | |
| 31 | /* |
| 32 | * Can be pkcs1 or raw, but pkcs1 is expected. |
| 33 | * This is just for argument checking, not necessarily passed to MbedTLS, |
| 34 | * For RSA signatures, MbedTLS typically supports the PKCS#1 v1.5 |
| 35 | * (aka. pkcs1) encoding by default. |
| 36 | * The library internally handles the details of decoding and verifying |
| 37 | * the signature according to the expected encoding for the specified algorithm. |
| 38 | */ |
| 39 | if (strcmp(sig->encoding, "pkcs1")) { |
| 40 | pr_err("Encoding %s is not supported, only supports pkcs1\n", |
| 41 | sig->encoding); |
| 42 | return -EINVAL; |
| 43 | } |
| 44 | |
| 45 | if (!strcmp(sig->hash_algo, "sha1")) |
| 46 | mb_hash_algo = MBEDTLS_MD_SHA1; |
| 47 | else if (!strcmp(sig->hash_algo, "sha224")) |
| 48 | mb_hash_algo = MBEDTLS_MD_SHA224; |
| 49 | else if (!strcmp(sig->hash_algo, "sha256")) |
| 50 | mb_hash_algo = MBEDTLS_MD_SHA256; |
| 51 | else if (!strcmp(sig->hash_algo, "sha384")) |
| 52 | mb_hash_algo = MBEDTLS_MD_SHA384; |
| 53 | else if (!strcmp(sig->hash_algo, "sha512")) |
| 54 | mb_hash_algo = MBEDTLS_MD_SHA512; |
| 55 | else /* Unknown or unsupported hash algorithm */ |
| 56 | return -EINVAL; |
| 57 | /* Initialize the mbedtls_pk_context with RSA key type */ |
| 58 | mbedtls_pk_init(&pk_ctx); |
| 59 | |
| 60 | /* Parse the DER-encoded public key */ |
| 61 | ret = mbedtls_pk_parse_public_key(&pk_ctx, pkey->key, pkey->keylen); |
| 62 | if (ret) { |
| 63 | pr_err("Failed to parse public key, ret:-0x%04x\n", -ret); |
| 64 | ret = -EINVAL; |
| 65 | goto err_key; |
| 66 | } |
| 67 | |
| 68 | /* Ensure that it is a RSA key */ |
| 69 | if (mbedtls_pk_get_type(&pk_ctx) != MBEDTLS_PK_RSA) { |
| 70 | pr_err("Only RSA keys are supported\n"); |
| 71 | ret = -EKEYREJECTED; |
| 72 | goto err_key; |
| 73 | } |
| 74 | |
| 75 | /* Verify the hash */ |
| 76 | ret = mbedtls_pk_verify(&pk_ctx, mb_hash_algo, sig->digest, |
| 77 | sig->digest_size, sig->s, sig->s_size); |
| 78 | |
| 79 | err_key: |
| 80 | mbedtls_pk_free(&pk_ctx); |
| 81 | return ret; |
| 82 | } |