1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 1999-2023 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci/* 11e1051a39Sopenharmony_ci * RSA low level APIs are deprecated for public use, but still ok for 12e1051a39Sopenharmony_ci * internal use. 13e1051a39Sopenharmony_ci */ 14e1051a39Sopenharmony_ci#include "internal/deprecated.h" 15e1051a39Sopenharmony_ci 16e1051a39Sopenharmony_ci#include <openssl/bn.h> 17e1051a39Sopenharmony_ci#include <openssl/err.h> 18e1051a39Sopenharmony_ci#include "crypto/rsa.h" 19e1051a39Sopenharmony_ci#include "rsa_local.h" 20e1051a39Sopenharmony_ci 21e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 22e1051a39Sopenharmony_cistatic int rsa_validate_keypair_multiprime(const RSA *key, BN_GENCB *cb) 23e1051a39Sopenharmony_ci{ 24e1051a39Sopenharmony_ci BIGNUM *i, *j, *k, *l, *m; 25e1051a39Sopenharmony_ci BN_CTX *ctx; 26e1051a39Sopenharmony_ci int ret = 1, ex_primes = 0, idx; 27e1051a39Sopenharmony_ci RSA_PRIME_INFO *pinfo; 28e1051a39Sopenharmony_ci 29e1051a39Sopenharmony_ci if (key->p == NULL || key->q == NULL || key->n == NULL 30e1051a39Sopenharmony_ci || key->e == NULL || key->d == NULL) { 31e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_RSA, RSA_R_VALUE_MISSING); 32e1051a39Sopenharmony_ci return 0; 33e1051a39Sopenharmony_ci } 34e1051a39Sopenharmony_ci 35e1051a39Sopenharmony_ci /* multi-prime? */ 36e1051a39Sopenharmony_ci if (key->version == RSA_ASN1_VERSION_MULTI) { 37e1051a39Sopenharmony_ci ex_primes = sk_RSA_PRIME_INFO_num(key->prime_infos); 38e1051a39Sopenharmony_ci if (ex_primes <= 0 39e1051a39Sopenharmony_ci || (ex_primes + 2) > ossl_rsa_multip_cap(BN_num_bits(key->n))) { 40e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_MULTI_PRIME_KEY); 41e1051a39Sopenharmony_ci return 0; 42e1051a39Sopenharmony_ci } 43e1051a39Sopenharmony_ci } 44e1051a39Sopenharmony_ci 45e1051a39Sopenharmony_ci i = BN_new(); 46e1051a39Sopenharmony_ci j = BN_new(); 47e1051a39Sopenharmony_ci k = BN_new(); 48e1051a39Sopenharmony_ci l = BN_new(); 49e1051a39Sopenharmony_ci m = BN_new(); 50e1051a39Sopenharmony_ci ctx = BN_CTX_new_ex(key->libctx); 51e1051a39Sopenharmony_ci if (i == NULL || j == NULL || k == NULL || l == NULL 52e1051a39Sopenharmony_ci || m == NULL || ctx == NULL) { 53e1051a39Sopenharmony_ci ret = -1; 54e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE); 55e1051a39Sopenharmony_ci goto err; 56e1051a39Sopenharmony_ci } 57e1051a39Sopenharmony_ci 58e1051a39Sopenharmony_ci if (BN_is_one(key->e)) { 59e1051a39Sopenharmony_ci ret = 0; 60e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_RSA, RSA_R_BAD_E_VALUE); 61e1051a39Sopenharmony_ci } 62e1051a39Sopenharmony_ci if (!BN_is_odd(key->e)) { 63e1051a39Sopenharmony_ci ret = 0; 64e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_RSA, RSA_R_BAD_E_VALUE); 65e1051a39Sopenharmony_ci } 66e1051a39Sopenharmony_ci 67e1051a39Sopenharmony_ci /* p prime? */ 68e1051a39Sopenharmony_ci if (BN_check_prime(key->p, ctx, cb) != 1) { 69e1051a39Sopenharmony_ci ret = 0; 70e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_RSA, RSA_R_P_NOT_PRIME); 71e1051a39Sopenharmony_ci } 72e1051a39Sopenharmony_ci 73e1051a39Sopenharmony_ci /* q prime? */ 74e1051a39Sopenharmony_ci if (BN_check_prime(key->q, ctx, cb) != 1) { 75e1051a39Sopenharmony_ci ret = 0; 76e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_RSA, RSA_R_Q_NOT_PRIME); 77e1051a39Sopenharmony_ci } 78e1051a39Sopenharmony_ci 79e1051a39Sopenharmony_ci /* r_i prime? */ 80e1051a39Sopenharmony_ci for (idx = 0; idx < ex_primes; idx++) { 81e1051a39Sopenharmony_ci pinfo = sk_RSA_PRIME_INFO_value(key->prime_infos, idx); 82e1051a39Sopenharmony_ci if (BN_check_prime(pinfo->r, ctx, cb) != 1) { 83e1051a39Sopenharmony_ci ret = 0; 84e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_RSA, RSA_R_MP_R_NOT_PRIME); 85e1051a39Sopenharmony_ci } 86e1051a39Sopenharmony_ci } 87e1051a39Sopenharmony_ci 88e1051a39Sopenharmony_ci /* n = p*q * r_3...r_i? */ 89e1051a39Sopenharmony_ci if (!BN_mul(i, key->p, key->q, ctx)) { 90e1051a39Sopenharmony_ci ret = -1; 91e1051a39Sopenharmony_ci goto err; 92e1051a39Sopenharmony_ci } 93e1051a39Sopenharmony_ci for (idx = 0; idx < ex_primes; idx++) { 94e1051a39Sopenharmony_ci pinfo = sk_RSA_PRIME_INFO_value(key->prime_infos, idx); 95e1051a39Sopenharmony_ci if (!BN_mul(i, i, pinfo->r, ctx)) { 96e1051a39Sopenharmony_ci ret = -1; 97e1051a39Sopenharmony_ci goto err; 98e1051a39Sopenharmony_ci } 99e1051a39Sopenharmony_ci } 100e1051a39Sopenharmony_ci if (BN_cmp(i, key->n) != 0) { 101e1051a39Sopenharmony_ci ret = 0; 102e1051a39Sopenharmony_ci if (ex_primes) 103e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_RSA, RSA_R_N_DOES_NOT_EQUAL_PRODUCT_OF_PRIMES); 104e1051a39Sopenharmony_ci else 105e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_RSA, RSA_R_N_DOES_NOT_EQUAL_P_Q); 106e1051a39Sopenharmony_ci } 107e1051a39Sopenharmony_ci 108e1051a39Sopenharmony_ci /* d*e = 1 mod \lambda(n)? */ 109e1051a39Sopenharmony_ci if (!BN_sub(i, key->p, BN_value_one())) { 110e1051a39Sopenharmony_ci ret = -1; 111e1051a39Sopenharmony_ci goto err; 112e1051a39Sopenharmony_ci } 113e1051a39Sopenharmony_ci if (!BN_sub(j, key->q, BN_value_one())) { 114e1051a39Sopenharmony_ci ret = -1; 115e1051a39Sopenharmony_ci goto err; 116e1051a39Sopenharmony_ci } 117e1051a39Sopenharmony_ci 118e1051a39Sopenharmony_ci /* now compute k = \lambda(n) = LCM(i, j, r_3 - 1...) */ 119e1051a39Sopenharmony_ci if (!BN_mul(l, i, j, ctx)) { 120e1051a39Sopenharmony_ci ret = -1; 121e1051a39Sopenharmony_ci goto err; 122e1051a39Sopenharmony_ci } 123e1051a39Sopenharmony_ci if (!BN_gcd(m, i, j, ctx)) { 124e1051a39Sopenharmony_ci ret = -1; 125e1051a39Sopenharmony_ci goto err; 126e1051a39Sopenharmony_ci } 127e1051a39Sopenharmony_ci if (!BN_div(m, NULL, l, m, ctx)) { /* remainder is 0 */ 128e1051a39Sopenharmony_ci ret = -1; 129e1051a39Sopenharmony_ci goto err; 130e1051a39Sopenharmony_ci } 131e1051a39Sopenharmony_ci for (idx = 0; idx < ex_primes; idx++) { 132e1051a39Sopenharmony_ci pinfo = sk_RSA_PRIME_INFO_value(key->prime_infos, idx); 133e1051a39Sopenharmony_ci if (!BN_sub(k, pinfo->r, BN_value_one())) { 134e1051a39Sopenharmony_ci ret = -1; 135e1051a39Sopenharmony_ci goto err; 136e1051a39Sopenharmony_ci } 137e1051a39Sopenharmony_ci if (!BN_mul(l, m, k, ctx)) { 138e1051a39Sopenharmony_ci ret = -1; 139e1051a39Sopenharmony_ci goto err; 140e1051a39Sopenharmony_ci } 141e1051a39Sopenharmony_ci if (!BN_gcd(m, m, k, ctx)) { 142e1051a39Sopenharmony_ci ret = -1; 143e1051a39Sopenharmony_ci goto err; 144e1051a39Sopenharmony_ci } 145e1051a39Sopenharmony_ci if (!BN_div(m, NULL, l, m, ctx)) { /* remainder is 0 */ 146e1051a39Sopenharmony_ci ret = -1; 147e1051a39Sopenharmony_ci goto err; 148e1051a39Sopenharmony_ci } 149e1051a39Sopenharmony_ci } 150e1051a39Sopenharmony_ci if (!BN_mod_mul(i, key->d, key->e, m, ctx)) { 151e1051a39Sopenharmony_ci ret = -1; 152e1051a39Sopenharmony_ci goto err; 153e1051a39Sopenharmony_ci } 154e1051a39Sopenharmony_ci 155e1051a39Sopenharmony_ci if (!BN_is_one(i)) { 156e1051a39Sopenharmony_ci ret = 0; 157e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_RSA, RSA_R_D_E_NOT_CONGRUENT_TO_1); 158e1051a39Sopenharmony_ci } 159e1051a39Sopenharmony_ci 160e1051a39Sopenharmony_ci if (key->dmp1 != NULL && key->dmq1 != NULL && key->iqmp != NULL) { 161e1051a39Sopenharmony_ci /* dmp1 = d mod (p-1)? */ 162e1051a39Sopenharmony_ci if (!BN_sub(i, key->p, BN_value_one())) { 163e1051a39Sopenharmony_ci ret = -1; 164e1051a39Sopenharmony_ci goto err; 165e1051a39Sopenharmony_ci } 166e1051a39Sopenharmony_ci if (!BN_mod(j, key->d, i, ctx)) { 167e1051a39Sopenharmony_ci ret = -1; 168e1051a39Sopenharmony_ci goto err; 169e1051a39Sopenharmony_ci } 170e1051a39Sopenharmony_ci if (BN_cmp(j, key->dmp1) != 0) { 171e1051a39Sopenharmony_ci ret = 0; 172e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_RSA, RSA_R_DMP1_NOT_CONGRUENT_TO_D); 173e1051a39Sopenharmony_ci } 174e1051a39Sopenharmony_ci 175e1051a39Sopenharmony_ci /* dmq1 = d mod (q-1)? */ 176e1051a39Sopenharmony_ci if (!BN_sub(i, key->q, BN_value_one())) { 177e1051a39Sopenharmony_ci ret = -1; 178e1051a39Sopenharmony_ci goto err; 179e1051a39Sopenharmony_ci } 180e1051a39Sopenharmony_ci if (!BN_mod(j, key->d, i, ctx)) { 181e1051a39Sopenharmony_ci ret = -1; 182e1051a39Sopenharmony_ci goto err; 183e1051a39Sopenharmony_ci } 184e1051a39Sopenharmony_ci if (BN_cmp(j, key->dmq1) != 0) { 185e1051a39Sopenharmony_ci ret = 0; 186e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_RSA, RSA_R_DMQ1_NOT_CONGRUENT_TO_D); 187e1051a39Sopenharmony_ci } 188e1051a39Sopenharmony_ci 189e1051a39Sopenharmony_ci /* iqmp = q^-1 mod p? */ 190e1051a39Sopenharmony_ci if (!BN_mod_inverse(i, key->q, key->p, ctx)) { 191e1051a39Sopenharmony_ci ret = -1; 192e1051a39Sopenharmony_ci goto err; 193e1051a39Sopenharmony_ci } 194e1051a39Sopenharmony_ci if (BN_cmp(i, key->iqmp) != 0) { 195e1051a39Sopenharmony_ci ret = 0; 196e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_RSA, RSA_R_IQMP_NOT_INVERSE_OF_Q); 197e1051a39Sopenharmony_ci } 198e1051a39Sopenharmony_ci } 199e1051a39Sopenharmony_ci 200e1051a39Sopenharmony_ci for (idx = 0; idx < ex_primes; idx++) { 201e1051a39Sopenharmony_ci pinfo = sk_RSA_PRIME_INFO_value(key->prime_infos, idx); 202e1051a39Sopenharmony_ci /* d_i = d mod (r_i - 1)? */ 203e1051a39Sopenharmony_ci if (!BN_sub(i, pinfo->r, BN_value_one())) { 204e1051a39Sopenharmony_ci ret = -1; 205e1051a39Sopenharmony_ci goto err; 206e1051a39Sopenharmony_ci } 207e1051a39Sopenharmony_ci if (!BN_mod(j, key->d, i, ctx)) { 208e1051a39Sopenharmony_ci ret = -1; 209e1051a39Sopenharmony_ci goto err; 210e1051a39Sopenharmony_ci } 211e1051a39Sopenharmony_ci if (BN_cmp(j, pinfo->d) != 0) { 212e1051a39Sopenharmony_ci ret = 0; 213e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_RSA, RSA_R_MP_EXPONENT_NOT_CONGRUENT_TO_D); 214e1051a39Sopenharmony_ci } 215e1051a39Sopenharmony_ci /* t_i = R_i ^ -1 mod r_i ? */ 216e1051a39Sopenharmony_ci if (!BN_mod_inverse(i, pinfo->pp, pinfo->r, ctx)) { 217e1051a39Sopenharmony_ci ret = -1; 218e1051a39Sopenharmony_ci goto err; 219e1051a39Sopenharmony_ci } 220e1051a39Sopenharmony_ci if (BN_cmp(i, pinfo->t) != 0) { 221e1051a39Sopenharmony_ci ret = 0; 222e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_RSA, RSA_R_MP_COEFFICIENT_NOT_INVERSE_OF_R); 223e1051a39Sopenharmony_ci } 224e1051a39Sopenharmony_ci } 225e1051a39Sopenharmony_ci 226e1051a39Sopenharmony_ci err: 227e1051a39Sopenharmony_ci BN_free(i); 228e1051a39Sopenharmony_ci BN_free(j); 229e1051a39Sopenharmony_ci BN_free(k); 230e1051a39Sopenharmony_ci BN_free(l); 231e1051a39Sopenharmony_ci BN_free(m); 232e1051a39Sopenharmony_ci BN_CTX_free(ctx); 233e1051a39Sopenharmony_ci return ret; 234e1051a39Sopenharmony_ci} 235e1051a39Sopenharmony_ci#endif /* FIPS_MODULE */ 236e1051a39Sopenharmony_ci 237e1051a39Sopenharmony_ciint ossl_rsa_validate_public(const RSA *key) 238e1051a39Sopenharmony_ci{ 239e1051a39Sopenharmony_ci return ossl_rsa_sp800_56b_check_public(key); 240e1051a39Sopenharmony_ci} 241e1051a39Sopenharmony_ci 242e1051a39Sopenharmony_ciint ossl_rsa_validate_private(const RSA *key) 243e1051a39Sopenharmony_ci{ 244e1051a39Sopenharmony_ci return ossl_rsa_sp800_56b_check_private(key); 245e1051a39Sopenharmony_ci} 246e1051a39Sopenharmony_ci 247e1051a39Sopenharmony_ciint ossl_rsa_validate_pairwise(const RSA *key) 248e1051a39Sopenharmony_ci{ 249e1051a39Sopenharmony_ci#ifdef FIPS_MODULE 250e1051a39Sopenharmony_ci return ossl_rsa_sp800_56b_check_keypair(key, NULL, -1, RSA_bits(key)); 251e1051a39Sopenharmony_ci#else 252e1051a39Sopenharmony_ci return rsa_validate_keypair_multiprime(key, NULL) > 0; 253e1051a39Sopenharmony_ci#endif 254e1051a39Sopenharmony_ci} 255e1051a39Sopenharmony_ci 256e1051a39Sopenharmony_ciint RSA_check_key(const RSA *key) 257e1051a39Sopenharmony_ci{ 258e1051a39Sopenharmony_ci return RSA_check_key_ex(key, NULL); 259e1051a39Sopenharmony_ci} 260e1051a39Sopenharmony_ci 261e1051a39Sopenharmony_ciint RSA_check_key_ex(const RSA *key, BN_GENCB *cb) 262e1051a39Sopenharmony_ci{ 263e1051a39Sopenharmony_ci#ifdef FIPS_MODULE 264e1051a39Sopenharmony_ci return ossl_rsa_validate_public(key) 265e1051a39Sopenharmony_ci && ossl_rsa_validate_private(key) 266e1051a39Sopenharmony_ci && ossl_rsa_validate_pairwise(key); 267e1051a39Sopenharmony_ci#else 268e1051a39Sopenharmony_ci return rsa_validate_keypair_multiprime(key, cb); 269e1051a39Sopenharmony_ci#endif /* FIPS_MODULE */ 270e1051a39Sopenharmony_ci} 271