1 /* $OpenBSD: rsa_chk.c,v 1.18 2023/07/08 12:26:45 beck Exp $ */ 2 /* ==================================================================== 3 * Copyright (c) 1999 The OpenSSL Project. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in 14 * the documentation and/or other materials provided with the 15 * distribution. 16 * 17 * 3. All advertising materials mentioning features or use of this 18 * software must display the following acknowledgment: 19 * "This product includes software developed by the OpenSSL Project 20 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 21 * 22 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 23 * endorse or promote products derived from this software without 24 * prior written permission. For written permission, please contact 25 * openssl-core@OpenSSL.org. 26 * 27 * 5. Products derived from this software may not be called "OpenSSL" 28 * nor may "OpenSSL" appear in their names without prior written 29 * permission of the OpenSSL Project. 30 * 31 * 6. Redistributions of any form whatsoever must retain the following 32 * acknowledgment: 33 * "This product includes software developed by the OpenSSL Project 34 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 35 * 36 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 37 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 38 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 39 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 40 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 41 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 42 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 43 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 44 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 45 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 46 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 47 * OF THE POSSIBILITY OF SUCH DAMAGE. 48 * ==================================================================== 49 */ 50 51 #include <openssl/bn.h> 52 #include <openssl/err.h> 53 #include <openssl/rsa.h> 54 55 #include "bn_local.h" 56 #include "rsa_local.h" 57 58 int 59 RSA_check_key(const RSA *key) 60 { 61 BIGNUM *i, *j, *k, *l, *m; 62 BN_CTX *ctx; 63 int r; 64 int ret = 1; 65 66 if (!key->p || !key->q || !key->n || !key->e || !key->d) { 67 RSAerror(RSA_R_VALUE_MISSING); 68 return 0; 69 } 70 71 i = BN_new(); 72 j = BN_new(); 73 k = BN_new(); 74 l = BN_new(); 75 m = BN_new(); 76 ctx = BN_CTX_new(); 77 if (i == NULL || j == NULL || k == NULL || l == NULL || m == NULL || 78 ctx == NULL) { 79 ret = -1; 80 RSAerror(ERR_R_MALLOC_FAILURE); 81 goto err; 82 } 83 84 if (BN_is_one(key->e)) { 85 ret = 0; 86 RSAerror(RSA_R_BAD_E_VALUE); 87 } 88 if (!BN_is_odd(key->e)) { 89 ret = 0; 90 RSAerror(RSA_R_BAD_E_VALUE); 91 } 92 93 /* p prime? */ 94 r = BN_is_prime_ex(key->p, BN_prime_checks, NULL, NULL); 95 if (r != 1) { 96 ret = r; 97 if (r != 0) 98 goto err; 99 RSAerror(RSA_R_P_NOT_PRIME); 100 } 101 102 /* q prime? */ 103 r = BN_is_prime_ex(key->q, BN_prime_checks, NULL, NULL); 104 if (r != 1) { 105 ret = r; 106 if (r != 0) 107 goto err; 108 RSAerror(RSA_R_Q_NOT_PRIME); 109 } 110 111 /* n = p*q? */ 112 r = BN_mul(i, key->p, key->q, ctx); 113 if (!r) { 114 ret = -1; 115 goto err; 116 } 117 118 if (BN_cmp(i, key->n) != 0) { 119 ret = 0; 120 RSAerror(RSA_R_N_DOES_NOT_EQUAL_P_Q); 121 } 122 123 /* d*e = 1 mod lcm(p-1,q-1)? */ 124 125 r = BN_sub(i, key->p, BN_value_one()); 126 if (!r) { 127 ret = -1; 128 goto err; 129 } 130 r = BN_sub(j, key->q, BN_value_one()); 131 if (!r) { 132 ret = -1; 133 goto err; 134 } 135 136 /* now compute k = lcm(i,j) */ 137 r = BN_mul(l, i, j, ctx); 138 if (!r) { 139 ret = -1; 140 goto err; 141 } 142 r = BN_gcd_ct(m, i, j, ctx); 143 if (!r) { 144 ret = -1; 145 goto err; 146 } 147 r = BN_div_ct(k, NULL, l, m, ctx); /* remainder is 0 */ 148 if (!r) { 149 ret = -1; 150 goto err; 151 } 152 153 r = BN_mod_mul(i, key->d, key->e, k, ctx); 154 if (!r) { 155 ret = -1; 156 goto err; 157 } 158 159 if (!BN_is_one(i)) { 160 ret = 0; 161 RSAerror(RSA_R_D_E_NOT_CONGRUENT_TO_1); 162 } 163 164 if (key->dmp1 != NULL && key->dmq1 != NULL && key->iqmp != NULL) { 165 /* dmp1 = d mod (p-1)? */ 166 r = BN_sub(i, key->p, BN_value_one()); 167 if (!r) { 168 ret = -1; 169 goto err; 170 } 171 172 r = BN_mod_ct(j, key->d, i, ctx); 173 if (!r) { 174 ret = -1; 175 goto err; 176 } 177 178 if (BN_cmp(j, key->dmp1) != 0) { 179 ret = 0; 180 RSAerror(RSA_R_DMP1_NOT_CONGRUENT_TO_D); 181 } 182 183 /* dmq1 = d mod (q-1)? */ 184 r = BN_sub(i, key->q, BN_value_one()); 185 if (!r) { 186 ret = -1; 187 goto err; 188 } 189 190 r = BN_mod_ct(j, key->d, i, ctx); 191 if (!r) { 192 ret = -1; 193 goto err; 194 } 195 196 if (BN_cmp(j, key->dmq1) != 0) { 197 ret = 0; 198 RSAerror(RSA_R_DMQ1_NOT_CONGRUENT_TO_D); 199 } 200 201 /* iqmp = q^-1 mod p? */ 202 if (BN_mod_inverse_ct(i, key->q, key->p, ctx) == NULL) { 203 ret = -1; 204 goto err; 205 } 206 207 if (BN_cmp(i, key->iqmp) != 0) { 208 ret = 0; 209 RSAerror(RSA_R_IQMP_NOT_INVERSE_OF_Q); 210 } 211 } 212 213 err: 214 BN_free(i); 215 BN_free(j); 216 BN_free(k); 217 BN_free(l); 218 BN_free(m); 219 BN_CTX_free(ctx); 220 221 return (ret); 222 } 223 LCRYPTO_ALIAS(RSA_check_key); 224