156083Skris/* crypto/rsa/rsa_chk.c -*- Mode: C; c-file-style: "eay" -*- */ 256083Skris/* ==================================================================== 356083Skris * Copyright (c) 1999 The OpenSSL Project. All rights reserved. 456083Skris * 556083Skris * Redistribution and use in source and binary forms, with or without 656083Skris * modification, are permitted provided that the following conditions 756083Skris * are met: 856083Skris * 956083Skris * 1. Redistributions of source code must retain the above copyright 10280304Sjkim * notice, this list of conditions and the following disclaimer. 1156083Skris * 1256083Skris * 2. Redistributions in binary form must reproduce the above copyright 1356083Skris * notice, this list of conditions and the following disclaimer in 1456083Skris * the documentation and/or other materials provided with the 1556083Skris * distribution. 1656083Skris * 1756083Skris * 3. All advertising materials mentioning features or use of this 1856083Skris * software must display the following acknowledgment: 1956083Skris * "This product includes software developed by the OpenSSL Project 2056083Skris * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 2156083Skris * 2256083Skris * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 2356083Skris * endorse or promote products derived from this software without 2456083Skris * prior written permission. For written permission, please contact 2556083Skris * openssl-core@OpenSSL.org. 2656083Skris * 2756083Skris * 5. Products derived from this software may not be called "OpenSSL" 2856083Skris * nor may "OpenSSL" appear in their names without prior written 2956083Skris * permission of the OpenSSL Project. 3056083Skris * 3156083Skris * 6. Redistributions of any form whatsoever must retain the following 3256083Skris * acknowledgment: 3356083Skris * "This product includes software developed by the OpenSSL Project 3456083Skris * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 3556083Skris * 3656083Skris * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 3756083Skris * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3856083Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 3956083Skris * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 4056083Skris * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 4156083Skris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 4256083Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 4356083Skris * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4456083Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 4556083Skris * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 4656083Skris * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 4756083Skris * OF THE POSSIBILITY OF SUCH DAMAGE. 4856083Skris * ==================================================================== 4956083Skris */ 5056083Skris 5156083Skris#include <openssl/bn.h> 5256083Skris#include <openssl/err.h> 5356083Skris#include <openssl/rsa.h> 5456083Skris 55109998Smarkmint RSA_check_key(const RSA *key) 56280304Sjkim{ 57280304Sjkim BIGNUM *i, *j, *k, *l, *m; 58280304Sjkim BN_CTX *ctx; 59280304Sjkim int r; 60280304Sjkim int ret = 1; 61264331Sjkim 62280304Sjkim if (!key->p || !key->q || !key->n || !key->e || !key->d) { 63280304Sjkim RSAerr(RSA_F_RSA_CHECK_KEY, RSA_R_VALUE_MISSING); 64280304Sjkim return 0; 65280304Sjkim } 6656083Skris 67280304Sjkim i = BN_new(); 68280304Sjkim j = BN_new(); 69280304Sjkim k = BN_new(); 70280304Sjkim l = BN_new(); 71280304Sjkim m = BN_new(); 72280304Sjkim ctx = BN_CTX_new(); 73280304Sjkim if (i == NULL || j == NULL || k == NULL || l == NULL || 74280304Sjkim m == NULL || ctx == NULL) { 75280304Sjkim ret = -1; 76280304Sjkim RSAerr(RSA_F_RSA_CHECK_KEY, ERR_R_MALLOC_FAILURE); 77280304Sjkim goto err; 78280304Sjkim } 7956083Skris 80280304Sjkim /* p prime? */ 81280304Sjkim r = BN_is_prime_ex(key->p, BN_prime_checks, NULL, NULL); 82280304Sjkim if (r != 1) { 83280304Sjkim ret = r; 84280304Sjkim if (r != 0) 85280304Sjkim goto err; 86280304Sjkim RSAerr(RSA_F_RSA_CHECK_KEY, RSA_R_P_NOT_PRIME); 87280304Sjkim } 8856083Skris 89280304Sjkim /* q prime? */ 90280304Sjkim r = BN_is_prime_ex(key->q, BN_prime_checks, NULL, NULL); 91280304Sjkim if (r != 1) { 92280304Sjkim ret = r; 93280304Sjkim if (r != 0) 94280304Sjkim goto err; 95280304Sjkim RSAerr(RSA_F_RSA_CHECK_KEY, RSA_R_Q_NOT_PRIME); 96280304Sjkim } 9756083Skris 98280304Sjkim /* n = p*q? */ 99280304Sjkim r = BN_mul(i, key->p, key->q, ctx); 100280304Sjkim if (!r) { 101280304Sjkim ret = -1; 102280304Sjkim goto err; 103280304Sjkim } 10456083Skris 105280304Sjkim if (BN_cmp(i, key->n) != 0) { 106280304Sjkim ret = 0; 107280304Sjkim RSAerr(RSA_F_RSA_CHECK_KEY, RSA_R_N_DOES_NOT_EQUAL_P_Q); 108280304Sjkim } 10956083Skris 110280304Sjkim /* d*e = 1 mod lcm(p-1,q-1)? */ 11156083Skris 112280304Sjkim r = BN_sub(i, key->p, BN_value_one()); 113280304Sjkim if (!r) { 114280304Sjkim ret = -1; 115280304Sjkim goto err; 116280304Sjkim } 117280304Sjkim r = BN_sub(j, key->q, BN_value_one()); 118280304Sjkim if (!r) { 119280304Sjkim ret = -1; 120280304Sjkim goto err; 121280304Sjkim } 12256083Skris 123280304Sjkim /* now compute k = lcm(i,j) */ 124280304Sjkim r = BN_mul(l, i, j, ctx); 125280304Sjkim if (!r) { 126280304Sjkim ret = -1; 127280304Sjkim goto err; 128280304Sjkim } 129280304Sjkim r = BN_gcd(m, i, j, ctx); 130280304Sjkim if (!r) { 131280304Sjkim ret = -1; 132280304Sjkim goto err; 133280304Sjkim } 134280304Sjkim r = BN_div(k, NULL, l, m, ctx); /* remainder is 0 */ 135280304Sjkim if (!r) { 136280304Sjkim ret = -1; 137280304Sjkim goto err; 138280304Sjkim } 13956083Skris 140280304Sjkim r = BN_mod_mul(i, key->d, key->e, k, ctx); 141280304Sjkim if (!r) { 142280304Sjkim ret = -1; 143280304Sjkim goto err; 144280304Sjkim } 145280304Sjkim 146280304Sjkim if (!BN_is_one(i)) { 147280304Sjkim ret = 0; 148280304Sjkim RSAerr(RSA_F_RSA_CHECK_KEY, RSA_R_D_E_NOT_CONGRUENT_TO_1); 149280304Sjkim } 150280304Sjkim 151280304Sjkim if (key->dmp1 != NULL && key->dmq1 != NULL && key->iqmp != NULL) { 152280304Sjkim /* dmp1 = d mod (p-1)? */ 153280304Sjkim r = BN_sub(i, key->p, BN_value_one()); 154280304Sjkim if (!r) { 155280304Sjkim ret = -1; 156280304Sjkim goto err; 157280304Sjkim } 158280304Sjkim 159280304Sjkim r = BN_mod(j, key->d, i, ctx); 160280304Sjkim if (!r) { 161280304Sjkim ret = -1; 162280304Sjkim goto err; 163280304Sjkim } 164280304Sjkim 165280304Sjkim if (BN_cmp(j, key->dmp1) != 0) { 166280304Sjkim ret = 0; 167280304Sjkim RSAerr(RSA_F_RSA_CHECK_KEY, RSA_R_DMP1_NOT_CONGRUENT_TO_D); 168280304Sjkim } 169280304Sjkim 170280304Sjkim /* dmq1 = d mod (q-1)? */ 171280304Sjkim r = BN_sub(i, key->q, BN_value_one()); 172280304Sjkim if (!r) { 173280304Sjkim ret = -1; 174280304Sjkim goto err; 175280304Sjkim } 176280304Sjkim 177280304Sjkim r = BN_mod(j, key->d, i, ctx); 178280304Sjkim if (!r) { 179280304Sjkim ret = -1; 180280304Sjkim goto err; 181280304Sjkim } 182280304Sjkim 183280304Sjkim if (BN_cmp(j, key->dmq1) != 0) { 184280304Sjkim ret = 0; 185280304Sjkim RSAerr(RSA_F_RSA_CHECK_KEY, RSA_R_DMQ1_NOT_CONGRUENT_TO_D); 186280304Sjkim } 187280304Sjkim 188280304Sjkim /* iqmp = q^-1 mod p? */ 189280304Sjkim if (!BN_mod_inverse(i, key->q, key->p, ctx)) { 190280304Sjkim ret = -1; 191280304Sjkim goto err; 192280304Sjkim } 193280304Sjkim 194280304Sjkim if (BN_cmp(i, key->iqmp) != 0) { 195280304Sjkim ret = 0; 196280304Sjkim RSAerr(RSA_F_RSA_CHECK_KEY, RSA_R_IQMP_NOT_INVERSE_OF_Q); 197280304Sjkim } 198280304Sjkim } 199280304Sjkim 20056083Skris err: 201280304Sjkim if (i != NULL) 202280304Sjkim BN_free(i); 203280304Sjkim if (j != NULL) 204280304Sjkim BN_free(j); 205280304Sjkim if (k != NULL) 206280304Sjkim BN_free(k); 207280304Sjkim if (l != NULL) 208280304Sjkim BN_free(l); 209280304Sjkim if (m != NULL) 210280304Sjkim BN_free(m); 211280304Sjkim if (ctx != NULL) 212280304Sjkim BN_CTX_free(ctx); 213280304Sjkim return (ret); 214280304Sjkim} 215