123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323 |
- /*
- * Copyright (C) 2016 Intel Corporation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
- #include "owndefs.h"
- #include "owncp.h"
- #include "pcpbn.h"
- #include "pcpprimeg.h"
- #include "pcpngrsa.h"
- #include "pcpngrsamontstuff.h"
- /*F*
- // Name: ippsRSA_ValidateKeys
- //
- // Purpose: Validate RSA keys
- //
- // Returns: Reason:
- // ippStsNullPtrErr NULL == pPublicKey
- // NULL == pPrivateKeyType2
- // NULL == pPrivateKeyType1
- // NULL == pBuffer
- // NULL == pPrimeGen
- // NULL == rndFunc
- // NULL == pResult
- //
- // ippStsContextMatchErr !RSA_PUB_KEY_VALID_ID(pPublicKey)
- // !RSA_PRV_KEY2_VALID_ID(pPrivateKeyType2)
- // !RSA_PRV_KEY1_VALID_ID(pPrivateKeyType1)
- // !PRIME_VALID_ID(pPrimeGen)
- //
- // ippStsIncompleteContextErr public and.or private key is not set up
- //
- // ippStsSizeErr PRIME_MAXBITSIZE(pPrimeGen) < factorPbitSize
- //
- // ippStsBadArgErr nTrials < 1
- //
- // ippStsNoErr no error
- //
- // Parameters:
- // pResult pointer to the validation result
- // pPublicKey pointer to the public key context
- // pPrivateKeyType2 pointer to the private key type2 context
- // pPrivateKeyType1 (optional) pointer to the private key type1 context
- // pBuffer pointer to the temporary buffer
- // nTrials parameter of Miller-Rabin Test
- // pPrimeGen pointer to the Prime generator context
- // rndFunc external PRNG
- // pRndParam pointer to the external PRNG parameters
- *F*/
- /*
- // make sure D*E = 1 mod(phi(P,Q))
- // where phi(P,Q) = (P-1)*(Q-1)
- */
- static
- int isValidPriv1_classic(const BNU_CHUNK_T* pN, int nsN,
- const BNU_CHUNK_T* pE, int nsE,
- const BNU_CHUNK_T* pD, int nsD,
- const BNU_CHUNK_T* pFactorP, int nsP,
- const BNU_CHUNK_T* pFactorQ, int nsQ,
- BNU_CHUNK_T* pBuffer)
- {
- BNU_CHUNK_T* pPhi = pBuffer;
- BNU_CHUNK_T* pProduct = pPhi + nsN;
- BNU_CHUNK_T c = cpSub_BNU(pPhi, pN, pFactorP, nsP);
- int prodLen;
- if(nsN>1) cpDec_BNU(pPhi+nsP, pN+nsP, nsQ, c);
- c = cpSub_BNU(pPhi,pPhi, pFactorQ, nsQ);
- if(nsN>1) cpDec_BNU(pPhi+nsQ, pPhi+nsQ, nsP, c);
- cpInc_BNU(pPhi, pPhi, nsP+nsQ, 1);
- cpMul_BNU_school(pProduct, pE, nsE, pD, nsD);
- prodLen = cpMod_BNU(pProduct, nsE+nsD, pPhi, nsN);
- return 1==cpEqu_BNU_CHUNK(pProduct, prodLen, 1)? IPP_IS_VALID : IPP_IS_INVALID;
- }
- /*
- // make sure D*E = 1 mod(lcm(P-1,Q-1))
- // where lcm(P-1,Q-1) = (P-1)*(Q-1)/gcd(P-1,Q-1)
- */
- static
- int isValidPriv1_rsa(const BNU_CHUNK_T* pN, int nsN,
- const BNU_CHUNK_T* pE, int nsE,
- const BNU_CHUNK_T* pD, int nsD,
- BNU_CHUNK_T* pFactorP, int nsP,
- BNU_CHUNK_T* pFactorQ, int nsQ,
- BNU_CHUNK_T* pBuffer)
- {
- __ALIGN8 IppsBigNumState tmpBN1;
- __ALIGN8 IppsBigNumState tmpBN2;
- __ALIGN8 IppsBigNumState tmpBN3;
- BNU_CHUNK_T* pProduct = pBuffer;
- BNU_CHUNK_T* pGcd = pProduct+(nsN+1);
- BNU_CHUNK_T* pLcm;
- int nsLcm;
- int prodLen;
- pBuffer = pGcd + (nsP+1)*2;
- /* P = P-1 and Q = Q-1 */
- pFactorP[0]--;
- pFactorQ[0]--;
- /* compute product (P-1)*(Q-1) = P*Q -P -Q +1 = N -(P-1) -(Q-1) -1 */
- {
- BNU_CHUNK_T c = cpSub_BNU(pProduct, pN, pFactorP, nsP);
- if(nsN>1) cpDec_BNU(pProduct+nsP, pN+nsP, nsQ, c);
- c = cpSub_BNU(pProduct, pProduct, pFactorQ, nsQ);
- if(nsN>1) cpDec_BNU(pProduct+nsQ, pProduct+nsQ, nsP, c);
- cpDec_BNU(pProduct, pProduct, nsN, 1);
- }
- /* compute gcd(p-1, q-1) */
- BN_Make(pGcd, pGcd+nsP+1, nsP, &tmpBN1); /* BN(gcd) */
- BN_SIZE(&tmpBN1) = nsP;
- BN_Make(pFactorP, pBuffer, nsP, &tmpBN2); /* BN(P-1) */
- BN_SIZE(&tmpBN2) = nsP;
- BN_Make(pFactorQ, pBuffer+nsP+1, nsQ, &tmpBN3); /* BN(Q-1) */
- BN_SIZE(&tmpBN3) = nsQ;
- ippsGcd_BN(&tmpBN2, &tmpBN3, &tmpBN1);
- /* compute lcm(p-1, q-1) = (p-1)(q-1)/gcd(p-1, q-1) */
- pLcm = pBuffer;
- cpDiv_BNU(pLcm, &nsLcm, pProduct, nsN, pGcd, BN_SIZE(&tmpBN1));
- /* test E*D = 1 mod lcm */
- cpMul_BNU_school(pProduct, pE, nsE, pD, nsD);
- prodLen = cpMod_BNU(pProduct, nsE+nsD, pLcm, nsLcm);
- /* restore P and Q */
- pFactorP[0]++;
- pFactorQ[0]++;
- return 1==cpEqu_BNU_CHUNK(pProduct, prodLen, 1)? IPP_IS_VALID : IPP_IS_INVALID;
- }
- IPPFUN(IppStatus, ippsRSA_ValidateKeys,(int* pResult,
- const IppsRSAPublicKeyState* pPublicKey,
- const IppsRSAPrivateKeyState* pPrivateKeyType2,
- const IppsRSAPrivateKeyState* pPrivateKeyType1, /*optional */
- Ipp8u* pBuffer,
- int nTrials,
- IppsPrimeState* pPrimeGen,
- IppBitSupplier rndFunc, void* pRndParam))
- {
- IPP_BAD_PTR1_RET(pPublicKey);
- pPublicKey = (IppsRSAPublicKeyState*)( IPP_ALIGNED_PTR(pPublicKey, RSA_PUBLIC_KEY_ALIGNMENT) );
- IPP_BADARG_RET(!RSA_PUB_KEY_VALID_ID(pPublicKey), ippStsContextMatchErr);
- IPP_BADARG_RET(!RSA_PUB_KEY_IS_SET(pPublicKey), ippStsIncompleteContextErr);
- IPP_BAD_PTR1_RET(pPrivateKeyType2);
- pPrivateKeyType2 = (IppsRSAPrivateKeyState*)( IPP_ALIGNED_PTR(pPrivateKeyType2, RSA_PRIVATE_KEY_ALIGNMENT) );
- IPP_BADARG_RET(!RSA_PRV_KEY2_VALID_ID(pPrivateKeyType2), ippStsContextMatchErr);
- IPP_BADARG_RET(!RSA_PRV_KEY_IS_SET(pPrivateKeyType2), ippStsIncompleteContextErr);
- if(pPrivateKeyType1) { /* pPrivateKeyType1 is optional */
- pPrivateKeyType1 = (IppsRSAPrivateKeyState*)( IPP_ALIGNED_PTR(pPrivateKeyType1, RSA_PRIVATE_KEY_ALIGNMENT) );
- IPP_BADARG_RET(!RSA_PRV_KEY1_VALID_ID(pPrivateKeyType1), ippStsContextMatchErr);
- IPP_BADARG_RET(!RSA_PRV_KEY_IS_SET(pPrivateKeyType1), ippStsIncompleteContextErr);
- }
- IPP_BAD_PTR1_RET(pPrimeGen);
- pPrimeGen = (IppsPrimeState*)( IPP_ALIGNED_PTR(pPrimeGen, PRIME_ALIGNMENT) );
- IPP_BADARG_RET(!PRIME_VALID_ID(pPrimeGen), ippStsContextMatchErr);
- IPP_BADARG_RET(PRIME_MAXBITSIZE(pPrimeGen) < RSA_PRV_KEY_BITSIZE_P(pPrivateKeyType2), ippStsSizeErr);
- IPP_BAD_PTR3_RET(pResult, pBuffer, rndFunc);
- /* test security parameter parameter */
- IPP_BADARG_RET((1>nTrials), ippStsBadArgErr);
- {
- BNU_CHUNK_T* pScratchBuffer = (BNU_CHUNK_T*)(IPP_ALIGNED_PTR(pBuffer, (int)sizeof(BNU_CHUNK_T)));
- /* E key component */
- BNU_CHUNK_T* pExpE = RSA_PUB_KEY_E(pPublicKey);
- cpSize nsE = BITS_BNU_CHUNK(RSA_PUB_KEY_BITSIZE_E(pPublicKey));
- /* P, dP, invQ key components */
- BNU_CHUNK_T* pFactorP= MNT_MODULUS(RSA_PRV_KEY_PMONT(pPrivateKeyType2));
- BNU_CHUNK_T* pExpDp = RSA_PRV_KEY_DP(pPrivateKeyType2);
- BNU_CHUNK_T* pInvQ = RSA_PRV_KEY_INVQ(pPrivateKeyType2);
- cpSize nsP = MNT_SIZE(RSA_PRV_KEY_PMONT(pPrivateKeyType2));
- /* Q, dQ key components */
- BNU_CHUNK_T* pFactorQ= MNT_MODULUS(RSA_PRV_KEY_QMONT(pPrivateKeyType2));
- BNU_CHUNK_T* pExpDq = RSA_PRV_KEY_DQ(pPrivateKeyType2);
- cpSize nsQ = MNT_SIZE(RSA_PRV_KEY_QMONT(pPrivateKeyType2));
- /*const*/ BNU_CHUNK_T* pN0 = MNT_MODULUS(RSA_PUB_KEY_NMONT(pPublicKey));
- cpSize nsN = MNT_SIZE(RSA_PUB_KEY_NMONT(pPublicKey));
- *pResult = IPP_IS_VALID;
- /* make sure P is prime */
- if(!cpPrimeTest(pFactorP, nsP, nTrials, pPrimeGen, rndFunc, pRndParam)) {
- *pResult = IPP_IS_COMPOSITE;
- return ippStsNoErr;
- }
- /* make sure Q is prime */
- if(!cpPrimeTest(pFactorQ, nsQ, nTrials, pPrimeGen, rndFunc, pRndParam)) {
- *pResult = IPP_IS_COMPOSITE;
- return ippStsNoErr;
- }
- /* make sure PubKey(N)==PrivKeytype2(N) and PubKey(N)==PrivKeytype1(N) */
- if(cpCmp_BNU(pN0, nsN,
- MNT_MODULUS(RSA_PRV_KEY_NMONT(pPrivateKeyType2)), MNT_SIZE(RSA_PRV_KEY_NMONT(pPrivateKeyType2)))) {
- *pResult = IPP_IS_INVALID;
- return ippStsNoErr;
- }
- if(pPrivateKeyType1) {
- if(cpCmp_BNU(pN0, nsN,
- MNT_MODULUS(RSA_PRV_KEY_NMONT(pPrivateKeyType1)), MNT_SIZE(RSA_PRV_KEY_NMONT(pPrivateKeyType1)))) {
- *pResult = IPP_IS_INVALID;
- return ippStsNoErr;
- }
- }
- /* make sure 3 <= E < N */
- if(1==nsE && pExpE[0]<3) {
- *pResult = IPP_IS_INVALID;
- return ippStsNoErr;
- }
- if(0 <= cpCmp_BNU(pExpE, nsE, pN0, nsN)) {
- *pResult = IPP_IS_INVALID;
- return ippStsNoErr;
- }
- {
- BNU_CHUNK_T* pFactor1 = pScratchBuffer;
- BNU_CHUNK_T* pInv = pFactor1 +nsP+1;
- BNU_CHUNK_T* pBufInv = pInv +nsP+1;
- BNU_CHUNK_T* pBufE = pBufInv +nsP+1;
- BNU_CHUNK_T* pBufFact = pBufE +nsP+1;
- BNU_CHUNK_T* pProduct = pBufInv;
- /* make sure E*dP = 1 mod (P-1) */
- cpDec_BNU(pFactor1, pFactorP, nsP, 1);
- cpMul_BNU_school(pProduct, pExpDp, nsP, pExpE, nsE);
- cpMod_BNU(pProduct, nsP+nsE, pFactor1, nsP);
- if(!cpEqu_BNU_CHUNK(pProduct, nsP, 1)) {
- *pResult = IPP_IS_INVALID;
- return ippStsNoErr;
- }
- /* make sure 1==GCD(E,P-1) => exist Inv(E,P-1) */
- if(!cpModInv_BNU(pInv, pExpE, nsE, pFactor1, nsP, pBufInv, pBufE, pBufFact)) {
- *pResult = IPP_IS_INVALID;
- return ippStsNoErr;
- }
- /* make sure E*dQ = 1 mod (Q-1) */
- cpDec_BNU(pFactor1, pFactorQ, nsQ, 1);
- cpMul_BNU_school(pProduct, pExpDq, nsQ, pExpE, nsE);
- cpMod_BNU(pProduct, nsQ+nsE, pFactor1, nsQ);
- if(!cpEqu_BNU_CHUNK(pProduct, nsQ, 1)) {
- *pResult = IPP_IS_INVALID;
- return ippStsNoErr;
- }
- /* make sure 1==GCD(E,Q-1) => exist Inv(E,Q-1) */
- if(!cpModInv_BNU(pInv, pExpE, nsE, pFactor1, nsQ, pBufInv, pBufE, pBufFact)) {
- *pResult = IPP_IS_INVALID;
- return ippStsNoErr;
- }
- }
- /* make sure Q*Qinv = 1 mod P */
- cpMontMul_BNU(pScratchBuffer,
- pFactorQ, nsQ,
- pInvQ, nsP,
- pFactorP, nsP, MNT_HELPER(RSA_PRV_KEY_PMONT(pPrivateKeyType2)),
- pScratchBuffer+nsP, NULL);
- if(!cpEqu_BNU_CHUNK(pScratchBuffer, nsP, 1)) {
- *pResult = IPP_IS_INVALID;
- return ippStsNoErr;
- }
- /* test priva exponent (optiobal) */
- if(pPrivateKeyType1) {
- const BNU_CHUNK_T* pExpD = RSA_PRV_KEY_D(pPrivateKeyType1);
- cpSize nsD = nsN;
- int resilt1 = isValidPriv1_classic(pN0,nsN, pExpE,nsE, pExpD,nsD,
- pFactorP,nsP, pFactorQ,nsQ,
- (BNU_CHUNK_T*)pScratchBuffer);
- int resilt2 = isValidPriv1_rsa(pN0,nsN, pExpE,nsE, pExpD,nsD,
- pFactorP,nsP, pFactorQ,nsQ,
- (BNU_CHUNK_T*)pScratchBuffer);
- if(IPP_IS_VALID!=resilt1 && IPP_IS_VALID!=resilt2) {
- *pResult = IPP_IS_INVALID;
- return ippStsNoErr;
- }
- }
- return ippStsNoErr;
- }
- }
|