at 25.11-pre 251 lines 9.2 kB view raw
1diff --git a/kernel-open/conftest.sh b/kernel-open/conftest.sh 2index fdceda72..3bfe39aa 100755 3--- a/kernel-open/conftest.sh 4+++ b/kernel-open/conftest.sh 5@@ -6721,6 +6721,47 @@ compile_test() { 6 compile_check_conftest "$CODE" "NV_CRYPTO_PRESENT" "" "symbols" 7 ;; 8 9+ crypto_akcipher_verify) 10+ # 11+ # Determine whether the crypto_akcipher_verify API is still present. 12+ # It was removed by commit 6b34562 ('crypto: akcipher - Drop sign/verify operations') 13+ # in v6.13-rc1 (2024-10-04). 14+ # 15+ # This test is dependent on the crypto conftest to determine whether crypto should be 16+ # enabled at all. That means that if the kernel is old enough such that crypto_akcipher_verify 17+ # 18+ # The test merely checks for the presence of the API, as it assumes that if the API 19+ # is no longer present, the new API to replace it (crypto_sig_verify) must be present. 20+ # If the kernel version is too old to have crypto_akcipher_verify, it will fail the crypto 21+ # conftest above and all crypto code will be compiled out. 22+ # 23+ CODE=" 24+ #include <crypto/akcipher.h> 25+ #include <linux/crypto.h> 26+ void conftest_crypto_akcipher_verify(void) { 27+ (void)crypto_akcipher_verify; 28+ }" 29+ 30+ compile_check_conftest "$CODE" "NV_CRYPTO_AKCIPHER_VERIFY_PRESENT" "" "symbols" 31+ ;; 32+ 33+ ecc_digits_from_bytes) 34+ # 35+ # Determine whether ecc_digits_from_bytes is present. 36+ # It was added in commit c6ab5c915da4 ('crypto: ecc - Prevent ecc_digits_from_bytes from 37+ # reading too many bytes') in v6.10. 38+ # 39+ # This functionality is needed when crypto_akcipher_verify is not present. 40+ # 41+ CODE=" 42+ #include <crypto/internal/ecc.h> 43+ void conftest_ecc_digits_from_bytes(void) { 44+ (void)ecc_digits_from_bytes; 45+ }" 46+ 47+ compile_check_conftest "$CODE" "NV_ECC_DIGITS_FROM_BYTES_PRESENT" "" "symbols" 48+ ;; 49+ 50 mempolicy_has_unified_nodes) 51 # 52 # Determine if the 'mempolicy' structure has 53diff --git a/kernel-open/nvidia/internal_crypt_lib.h b/kernel-open/nvidia/internal_crypt_lib.h 54index 2eac7d5e..917acb26 100644 55--- a/kernel-open/nvidia/internal_crypt_lib.h 56+++ b/kernel-open/nvidia/internal_crypt_lib.h 57@@ -64,7 +64,9 @@ 58 * old or even just user disabled. If we should use LKCA, include headers, else 59 * define stubs to return errors. 60 */ 61-#if defined(NV_CRYPTO_PRESENT) && defined (NV_CONFIG_CRYPTO_PRESENT) 62+#if defined(NV_CRYPTO_PRESENT) && defined (NV_CONFIG_CRYPTO_PRESENT) && \ 63+ (defined(NV_CRYPTO_AKCIPHER_VERIFY_PRESENT) || \ 64+ (defined(NV_CRYPTO_SIG_H_PRESENT) && defined(NV_ECC_DIGITS_FROM_BYTES_PRESENT))) 65 #define USE_LKCA 1 66 #endif 67 68diff --git a/kernel-open/nvidia/libspdm_ecc.c b/kernel-open/nvidia/libspdm_ecc.c 69index 1f8f0100..a9eb4db5 100644 70--- a/kernel-open/nvidia/libspdm_ecc.c 71+++ b/kernel-open/nvidia/libspdm_ecc.c 72@@ -30,14 +30,26 @@ MODULE_SOFTDEP("pre: ecdh_generic,ecdsa_generic"); 73 #include <crypto/akcipher.h> 74 #include <crypto/ecdh.h> 75 #include <crypto/internal/ecc.h> 76+#ifndef NV_CRYPTO_AKCIPHER_VERIFY_PRESENT 77+#include <crypto/sig.h> 78+ 79+struct signature 80+{ 81+ u64 r[ECC_MAX_DIGITS]; 82+ u64 s[ECC_MAX_DIGITS]; 83+}; 84+#endif // NV_CRYPTO_AKCIPHER_VERIFY_PRESENT 85+ 86+#define ECDSA_PUBKEY_HEADER_XY_PRESENT (0x4) 87 88 struct ecc_ctx { 89 unsigned int curve_id; 90 u64 priv_key[ECC_MAX_DIGITS]; // In big endian 91 92 struct { 93- // ecdsa wants byte preceding pub_key to be set to '4' 94- u64 pub_key_prefix; 95+ // ecdsa pubkey has header indicating length of pubkey 96+ u8 padding[7]; 97+ u8 pub_key_prefix; 98 u64 pub_key[2 * ECC_MAX_DIGITS]; 99 }; 100 101@@ -221,25 +233,84 @@ bool lkca_ec_compute_key(void *ec_context, const uint8_t *peer_public, 102 #endif 103 } 104 105-bool lkca_ecdsa_verify(void *ec_context, size_t hash_nid, 106- const uint8_t *message_hash, size_t hash_size, 107- const uint8_t *signature, size_t sig_size) 108+#ifndef NV_CRYPTO_AKCIPHER_VERIFY_PRESENT 109+static bool lkca_ecdsa_verify_crypto_sig(void *ec_context, size_t hash_nid, 110+ const uint8_t *message_hash, size_t hash_size, 111+ const uint8_t *signature, size_t sig_size) 112 { 113 #ifndef USE_LKCA 114 return false; 115 #else 116 struct ecc_ctx *ctx = ec_context; 117+ u8 *pub_key; 118+ int err; 119+ DECLARE_CRYPTO_WAIT(wait); 120+ struct crypto_sig * tfm = NULL; 121+ struct signature sig; 122+ 123+ if (sig_size != ctx->size || !ctx->pub_key_set) 124+ { 125+ return false; 126+ } 127+ 128+ tfm = crypto_alloc_sig(ctx->name, CRYPTO_ALG_TYPE_SIG, 0); 129+ if (IS_ERR(tfm)) { 130+ pr_info("crypto_alloc_sig failed in lkca_ecdsa_verify\n"); 131+ return false; 132+ } 133+ 134+ // modify header of pubkey to indicate size 135+ pub_key = (u8 *) &(ctx->pub_key_prefix); 136+ *pub_key = ECDSA_PUBKEY_HEADER_XY_PRESENT; 137+ err = crypto_sig_set_pubkey(tfm, pub_key, ctx->size + 1); 138+ if (err != 0) 139+ { 140+ pr_info("crypto_sig_set_pubkey failed in lkca_ecdsa_verify: %d", -err); 141+ goto failTfm; 142+ } 143+ 144+ // 145+ // Compared to the way we receive the signature, we need to: 146+ // - swap order of all digits 147+ // - swap endianness for each digit 148+ // 149+ memset(&sig, 0, sizeof(sig)); 150+ ecc_digits_from_bytes(signature, ctx->size/2, sig.r, ECC_MAX_DIGITS); 151+ ecc_digits_from_bytes(signature + ctx->size/2, ctx->size/2, sig.s, ECC_MAX_DIGITS); 152+ 153+ err = crypto_sig_verify(tfm, (void *)&sig, sizeof(sig), message_hash, hash_size); 154+ if (err != 0) 155+ { 156+ pr_info("crypto_sig_verify failed in lkca_ecdsa_verify %d\n", -err); 157+ } 158+ 159+failTfm: 160+ crypto_free_sig(tfm); 161+ 162+ return err == 0; 163+#endif // USE_LKCA 164+} 165+ 166+#else // NV_CRYPTO_AKCIPHER_VERIFY_PRESENT 167+static bool lkca_ecdsa_verify_akcipher(void *ec_context, size_t hash_nid, 168+ const uint8_t *message_hash, size_t hash_size, 169+ const uint8_t *signature, size_t sig_size) 170+{ 171+#ifndef USE_LKCA 172+ return false; 173+#else // USE_LKCA 174+ struct ecc_ctx *ctx = ec_context; 175+ u8 *pub_key; 176+ int err; 177+ DECLARE_CRYPTO_WAIT(wait); 178 179 // Roundabout way 180 u64 ber_max_len = 3 + 2 * (4 + (ECC_MAX_BYTES)); 181 u64 ber_len = 0; 182 u8 *ber = NULL; 183- u8 *pub_key; 184 struct akcipher_request *req = NULL; 185 struct crypto_akcipher *tfm = NULL; 186 struct scatterlist sg; 187- DECLARE_CRYPTO_WAIT(wait); 188- int err; 189 190 if (sig_size != ctx->size) { 191 return false; 192@@ -251,21 +322,21 @@ bool lkca_ecdsa_verify(void *ec_context, size_t hash_nid, 193 194 tfm = crypto_alloc_akcipher(ctx->name, CRYPTO_ALG_TYPE_AKCIPHER, 0); 195 if (IS_ERR(tfm)) { 196- pr_info("ALLOC FAILED\n"); 197+ pr_info("crypto_alloc_akcipher failed in lkca_ecdsa_verify\n"); 198 return false; 199 } 200 201- pub_key = (u8 *) ctx->pub_key; 202- pub_key--; // Go back into byte of pub_key_prefix 203- *pub_key = 4; // And set it to 4 to placate kernel 204+ // modify header of pubkey to indicate size 205+ pub_key = (u8 *) &(ctx->pub_key_prefix); 206+ *pub_key = ECDSA_PUBKEY_HEADER_XY_PRESENT; 207 if ((err = crypto_akcipher_set_pub_key(tfm, pub_key, ctx->size + 1)) != 0) { 208- pr_info("SET PUB KEY FAILED: %d\n", -err); 209+ pr_info("crypto_akcipher_set_pub_key failed in lkca_ecdsa_verify: %d\n", -err); 210 goto failTfm; 211 } 212 213 req = akcipher_request_alloc(tfm, GFP_KERNEL); 214 if (IS_ERR(req)) { 215- pr_info("REQUEST ALLOC FAILED\n"); 216+ pr_info("akcipher_request_alloc failed in lkca_ecdsa_verify\n"); 217 goto failTfm; 218 } 219 220@@ -310,9 +381,8 @@ bool lkca_ecdsa_verify(void *ec_context, size_t hash_nid, 221 CRYPTO_TFM_REQ_MAY_SLEEP, crypto_req_done, &wait); 222 akcipher_request_set_crypt(req, &sg, NULL, ber_len, hash_size); 223 err = crypto_wait_req(crypto_akcipher_verify(req), &wait); 224- 225 if (err != 0){ 226- pr_info("Verify FAILED %d\n", -err); 227+ pr_info("crypto_akcipher_verify failed in lkca_ecdsa_verify %d\n", -err); 228 } 229 230 kfree(ber); 231@@ -322,5 +392,19 @@ failTfm: 232 crypto_free_akcipher(tfm); 233 234 return err == 0; 235-#endif 236+#endif // USE_LKCA 237+} 238+#endif // NV_CRYPTO_AKCIPHER_VERIFY_PRESENT 239+ 240+bool lkca_ecdsa_verify(void *ec_context, size_t hash_nid, 241+ const uint8_t *message_hash, size_t hash_size, 242+ const uint8_t *signature, size_t sig_size) 243+{ 244+#ifndef NV_CRYPTO_AKCIPHER_VERIFY_PRESENT 245+ return lkca_ecdsa_verify_crypto_sig(ec_context, hash_nid, message_hash, hash_size, 246+ signature, sig_size); 247+#else // NV_CRYPTO_AKCIPHER_VERIFY_PRESENT 248+ return lkca_ecdsa_verify_akcipher(ec_context, hash_nid, message_hash, hash_size, 249+ signature, sig_size); 250+#endif // NV_CRYPTO_AKCIPHER_VERIFY_PRESENT 251 }