206 lines
4.7 KiB
C
206 lines
4.7 KiB
C
/** \ingroup RSA_m
|
|
* \file rsakp.c
|
|
*
|
|
* RSA Keypair, code.
|
|
*/
|
|
|
|
/*
|
|
* <conformance statement for IEEE P1363 needed here>
|
|
*
|
|
* Copyright (c) 2000 Virtual Unlimited B.V.
|
|
*
|
|
* Author: Bob Deblier <bob@virtualunlimited.com>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*
|
|
*/
|
|
|
|
#include "system.h"
|
|
#include "rsakp.h"
|
|
#include "mp32prime.h"
|
|
#include "mp32.h"
|
|
#include "debug.h"
|
|
|
|
/*@-boundswrite@*/
|
|
int rsakpMake(rsakp* kp, randomGeneratorContext* rgc, int nsize)
|
|
{
|
|
/*
|
|
* Generates an RSA Keypair for use with the Chinese Remainder Theorem
|
|
*/
|
|
|
|
register uint32 pqsize = ((uint32)(nsize+1)) >> 1;
|
|
register uint32* temp = (uint32*) malloc((16*pqsize+6) * sizeof(*temp));
|
|
register uint32 newn = 1;
|
|
|
|
if (temp)
|
|
{
|
|
mp32barrett r, psubone, qsubone, phi;
|
|
|
|
nsize = pqsize << 1;
|
|
|
|
/* set e */
|
|
mp32nsetw(&kp->e, 65535);
|
|
|
|
/* generate a random prime p and q */
|
|
/*@-globs@*/
|
|
mp32prnd_w(&kp->p, rgc, pqsize, mp32ptrials(pqsize << 5), &kp->e, temp);
|
|
mp32prnd_w(&kp->q, rgc, pqsize, mp32ptrials(pqsize << 5), &kp->e, temp);
|
|
/*@-globs@*/
|
|
|
|
/* if p <= q, perform a swap to make p larger than q */
|
|
if (mp32le(pqsize, kp->p.modl, kp->q.modl))
|
|
{
|
|
/*@-sizeoftype@*/
|
|
memcpy(&r, &kp->q, sizeof(mp32barrett));
|
|
memcpy(&kp->q, &kp->p, sizeof(mp32barrett));
|
|
memcpy(&kp->p, &r, sizeof(mp32barrett));
|
|
/*@=sizeoftype@*/
|
|
}
|
|
|
|
mp32bzero(&r);
|
|
mp32bzero(&psubone);
|
|
mp32bzero(&qsubone);
|
|
mp32bzero(&phi);
|
|
|
|
while (1)
|
|
{
|
|
mp32mul(temp, pqsize, kp->p.modl, pqsize, kp->q.modl);
|
|
|
|
if (newn && mp32msbset(nsize, temp))
|
|
break;
|
|
|
|
/* product of p and q doesn't have the required size (one bit short) */
|
|
|
|
/*@-globs@*/
|
|
mp32prnd_w(&r, rgc, pqsize, mp32ptrials(pqsize << 5), &kp->e, temp);
|
|
/*@=globs@*/
|
|
|
|
/*@-usedef -branchstate @*/ /* r is set */
|
|
if (mp32le(pqsize, kp->p.modl, r.modl))
|
|
{
|
|
mp32bfree(&kp->q);
|
|
/*@-sizeoftype@*/
|
|
memcpy(&kp->q, &kp->p, sizeof(mp32barrett));
|
|
memcpy(&kp->p, &r, sizeof(mp32barrett));
|
|
/*@=sizeoftype@*/
|
|
mp32bzero(&r);
|
|
newn = 1;
|
|
}
|
|
else if (mp32le(pqsize, kp->q.modl, r.modl))
|
|
{
|
|
mp32bfree(&kp->q);
|
|
/*@-sizeoftype@*/
|
|
memcpy(&kp->q, &r, sizeof(mp32barrett));
|
|
/*@=sizeoftype@*/
|
|
mp32bzero(&r);
|
|
newn = 1;
|
|
}
|
|
else
|
|
{
|
|
mp32bfree(&r);
|
|
newn = 0;
|
|
}
|
|
/*@=usedef =branchstate @*/
|
|
}
|
|
|
|
mp32bset(&kp->n, nsize, temp);
|
|
|
|
/* compute p-1 */
|
|
mp32bsubone(&kp->p, temp);
|
|
mp32bset(&psubone, pqsize, temp);
|
|
|
|
/* compute q-1 */
|
|
mp32bsubone(&kp->q, temp);
|
|
mp32bset(&qsubone, pqsize, temp);
|
|
|
|
/*@-usedef@*/ /* psubone/qsubone are set */
|
|
/* compute phi = (p-1)*(q-1) */
|
|
mp32mul(temp, pqsize, psubone.modl, pqsize, qsubone.modl);
|
|
mp32bset(&phi, nsize, temp);
|
|
|
|
/* compute d = inv(e) mod phi */
|
|
mp32nsize(&kp->d, nsize);
|
|
(void) mp32binv_w(&phi, kp->e.size, kp->e.data, kp->d.data, temp);
|
|
|
|
/* compute d1 = d mod (p-1) */
|
|
mp32nsize(&kp->d1, pqsize);
|
|
mp32bmod_w(&psubone, kp->d.data, kp->d1.data, temp);
|
|
|
|
/* compute d2 = d mod (q-1) */
|
|
mp32nsize(&kp->d2, pqsize);
|
|
mp32bmod_w(&qsubone, kp->d.data, kp->d2.data, temp);
|
|
|
|
/* compute c = inv(q) mod p */
|
|
mp32nsize(&kp->c, pqsize);
|
|
(void) mp32binv_w(&kp->p, pqsize, kp->q.modl, kp->c.data, temp);
|
|
|
|
free(temp);
|
|
/*@=usedef@*/
|
|
|
|
return 0;
|
|
}
|
|
return -1;
|
|
}
|
|
/*@=boundswrite@*/
|
|
|
|
/*@-boundswrite@*/
|
|
int rsakpInit(rsakp* kp)
|
|
{
|
|
memset(kp, 0, sizeof(*kp));
|
|
/* or
|
|
mp32bzero(&kp->n);
|
|
mp32nzero(&kp->e);
|
|
mp32nzero(&kp->d);
|
|
mp32bzero(&kp->p);
|
|
mp32bzero(&kp->q);
|
|
mp32nzero(&kp->d1);
|
|
mp32nzero(&kp->d2);
|
|
mp32nzero(&kp->c);
|
|
*/
|
|
|
|
return 0;
|
|
}
|
|
/*@=boundswrite@*/
|
|
|
|
int rsakpFree(rsakp* kp)
|
|
{
|
|
/*@-usereleased -compdef @*/ /* kp->param.{n,p,q}.modl is OK */
|
|
mp32bfree(&kp->n);
|
|
mp32nfree(&kp->e);
|
|
mp32nfree(&kp->d);
|
|
mp32bfree(&kp->p);
|
|
mp32bfree(&kp->q);
|
|
mp32nfree(&kp->d1);
|
|
mp32nfree(&kp->d2);
|
|
mp32nfree(&kp->c);
|
|
|
|
return 0;
|
|
/*@=usereleased =compdef @*/
|
|
}
|
|
|
|
int rsakpCopy(rsakp* dst, const rsakp* src)
|
|
{
|
|
mp32bcopy(&dst->n, &src->n);
|
|
mp32ncopy(&dst->e, &src->e);
|
|
mp32ncopy(&dst->d, &src->d);
|
|
mp32bcopy(&dst->p, &src->p);
|
|
mp32bcopy(&dst->q, &src->q);
|
|
mp32ncopy(&dst->d1, &src->d1);
|
|
mp32ncopy(&dst->d2, &src->d2);
|
|
mp32ncopy(&dst->c, &src->c);
|
|
|
|
return 0;
|
|
}
|