1 /* $OpenBSD: rsa_chk.c,v 1.8 2014/07/09 19:51:38 jsing 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 int 56 RSA_check_key(const RSA *key) 57 { 58 BIGNUM *i, *j, *k, *l, *m; 59 BN_CTX *ctx; 60 int r; 61 int ret = 1; 62 63 if (!key->p || !key->q || !key->n || !key->e || !key->d) { 64 RSAerr(RSA_F_RSA_CHECK_KEY, RSA_R_VALUE_MISSING); 65 return 0; 66 } 67 68 i = BN_new(); 69 j = BN_new(); 70 k = BN_new(); 71 l = BN_new(); 72 m = BN_new(); 73 ctx = BN_CTX_new(); 74 if (i == NULL || j == NULL || k == NULL || l == NULL || m == NULL || 75 ctx == NULL) { 76 ret = -1; 77 RSAerr(RSA_F_RSA_CHECK_KEY, ERR_R_MALLOC_FAILURE); 78 goto err; 79 } 80 81 /* p prime? */ 82 r = BN_is_prime_ex(key->p, BN_prime_checks, NULL, NULL); 83 if (r != 1) { 84 ret = r; 85 if (r != 0) 86 goto err; 87 RSAerr(RSA_F_RSA_CHECK_KEY, RSA_R_P_NOT_PRIME); 88 } 89 90 /* q prime? */ 91 r = BN_is_prime_ex(key->q, BN_prime_checks, NULL, NULL); 92 if (r != 1) { 93 ret = r; 94 if (r != 0) 95 goto err; 96 RSAerr(RSA_F_RSA_CHECK_KEY, RSA_R_Q_NOT_PRIME); 97 } 98 99 /* n = p*q? */ 100 r = BN_mul(i, key->p, key->q, ctx); 101 if (!r) { 102 ret = -1; 103 goto err; 104 } 105 106 if (BN_cmp(i, key->n) != 0) { 107 ret = 0; 108 RSAerr(RSA_F_RSA_CHECK_KEY, RSA_R_N_DOES_NOT_EQUAL_P_Q); 109 } 110 111 /* d*e = 1 mod lcm(p-1,q-1)? */ 112 113 r = BN_sub(i, key->p, BN_value_one()); 114 if (!r) { 115 ret = -1; 116 goto err; 117 } 118 r = BN_sub(j, key->q, BN_value_one()); 119 if (!r) { 120 ret = -1; 121 goto err; 122 } 123 124 /* now compute k = lcm(i,j) */ 125 r = BN_mul(l, i, j, ctx); 126 if (!r) { 127 ret = -1; 128 goto err; 129 } 130 r = BN_gcd(m, i, j, ctx); 131 if (!r) { 132 ret = -1; 133 goto err; 134 } 135 r = BN_div(k, NULL, l, m, ctx); /* remainder is 0 */ 136 if (!r) { 137 ret = -1; 138 goto err; 139 } 140 141 r = BN_mod_mul(i, key->d, key->e, k, ctx); 142 if (!r) { 143 ret = -1; 144 goto err; 145 } 146 147 if (!BN_is_one(i)) { 148 ret = 0; 149 RSAerr(RSA_F_RSA_CHECK_KEY, RSA_R_D_E_NOT_CONGRUENT_TO_1); 150 } 151 152 if (key->dmp1 != NULL && key->dmq1 != NULL && key->iqmp != NULL) { 153 /* dmp1 = d mod (p-1)? */ 154 r = BN_sub(i, key->p, BN_value_one()); 155 if (!r) { 156 ret = -1; 157 goto err; 158 } 159 160 r = BN_mod(j, key->d, i, ctx); 161 if (!r) { 162 ret = -1; 163 goto err; 164 } 165 166 if (BN_cmp(j, key->dmp1) != 0) { 167 ret = 0; 168 RSAerr(RSA_F_RSA_CHECK_KEY, 169 RSA_R_DMP1_NOT_CONGRUENT_TO_D); 170 } 171 172 /* dmq1 = d mod (q-1)? */ 173 r = BN_sub(i, key->q, BN_value_one()); 174 if (!r) { 175 ret = -1; 176 goto err; 177 } 178 179 r = BN_mod(j, key->d, i, ctx); 180 if (!r) { 181 ret = -1; 182 goto err; 183 } 184 185 if (BN_cmp(j, key->dmq1) != 0) { 186 ret = 0; 187 RSAerr(RSA_F_RSA_CHECK_KEY, 188 RSA_R_DMQ1_NOT_CONGRUENT_TO_D); 189 } 190 191 /* iqmp = q^-1 mod p? */ 192 if (!BN_mod_inverse(i, key->q, key->p, ctx)) { 193 ret = -1; 194 goto err; 195 } 196 197 if (BN_cmp(i, key->iqmp) != 0) { 198 ret = 0; 199 RSAerr(RSA_F_RSA_CHECK_KEY, 200 RSA_R_IQMP_NOT_INVERSE_OF_Q); 201 } 202 } 203 204 err: 205 BN_free(i); 206 BN_free(j); 207 BN_free(k); 208 BN_free(l); 209 BN_free(m); 210 BN_CTX_free(ctx); 211 212 return (ret); 213 } 214