first and last commit
This commit is contained in:
commit
1bf4efd552
2612 files changed
+636500
No files matched your search
@@ -0,0 +1,383 @@
|
||||
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
|
||||
|
||||
/*
|
||||
* libgRSA.h - public API for RSA library based on libGiants
|
||||
*
|
||||
* Created Aug. 9 2005 by Doug Mitchell.
|
||||
*/
|
||||
|
||||
#include <libgRSA/libgRSA.h>
|
||||
#include <libgRSA/libgRSA_config.h>
|
||||
#include <libgRSA/rsaPadding.h>
|
||||
#include <libgRSA/libgRSA_priv.h>
|
||||
#include <libGiants/giantIntegers.h>
|
||||
#include <libGiants/giantExternal.h>
|
||||
#include <libGiants/giantMod.h>
|
||||
#include <libGiants/giantDebug.h>
|
||||
|
||||
#define SIG_DEBUG 0
|
||||
#if SIG_DEBUG
|
||||
static void showGiant(const char *label, giant g)
|
||||
{
|
||||
printf("%s: ", label);
|
||||
printGiantHex(g);
|
||||
}
|
||||
#else
|
||||
#define showGiant(l, g)
|
||||
#endif
|
||||
|
||||
#if RSA_PUB_KEY_ENABLE
|
||||
|
||||
/* lazy evaluation RSAPubGiantKey->recip */
|
||||
static void rsaEnsurePubRecip(
|
||||
RSAPubGiantKey *pubKey)
|
||||
{
|
||||
GI_CHECK_SP("rsaEnsurePubRecip");
|
||||
if(pubKey->recip.g.sign != 0) {
|
||||
return;
|
||||
}
|
||||
GI_LOG_SP("rsaEnsurePubRecip calling make_recip");
|
||||
make_recip(&pubKey->n.g, &pubKey->recip.g);
|
||||
}
|
||||
|
||||
#endif /* RSA_PUB_KEY_ENABLE */
|
||||
|
||||
#if RSA_PRIV_KEY_ENABLE
|
||||
|
||||
/* lazy evaluation RSAPrivGiantKey->{pRecip,qRecip} */
|
||||
static void rsaEnsurePrivRecip(
|
||||
RSAPrivGiantKey *privKey)
|
||||
{
|
||||
GI_CHECK_SP("rsaEnsurePrivRecip");
|
||||
if(privKey->pRecip.g.sign != 0) {
|
||||
return;
|
||||
}
|
||||
GI_LOG_SP("rsaEnsurePrivbRecip calling make_recip");
|
||||
make_recip(&privKey->p.g, &privKey->pRecip.g);
|
||||
make_recip(&privKey->q.g, &privKey->qRecip.g);
|
||||
}
|
||||
|
||||
#endif /* RSA_PRIV_KEY_ENABLE */
|
||||
|
||||
#if RSA_SIGN_ENABLE
|
||||
|
||||
RSAStatus RSA_Sign(
|
||||
RSAPrivGiantKey *privKey, /* private key */
|
||||
RSAPadding padding, /* RP_None or RP_PKCS1 */
|
||||
const gi_uint8 *dataToSign, /* signature over this data */
|
||||
gi_uint16 dataToSignLen, /* length of dataToSign */
|
||||
#if RSA_SIG_SHARE_GIANT
|
||||
RSASignBuffer *signBuffer, /* signature RETURNED here */
|
||||
#else
|
||||
gi_uint8 *sig, /* signature, RETURNED */
|
||||
#endif
|
||||
gi_uint16 *sigLen) /* IN/OUT if !RSA_SIG_SHARE_GIANT */
|
||||
/* OUT only if RSA_SIG_SHARE_GIANT */
|
||||
{
|
||||
RSAStatus rtn = RSA_Success;
|
||||
lgiant ptSigGiant; /* in/out for powermodCRT */
|
||||
gi_uint16 modSize;
|
||||
GIReturn grtn;
|
||||
#if !RSA_SIG_SHARE_GIANT
|
||||
/* powermodCRT needs this one way or another */
|
||||
lgiant powermodScratch;
|
||||
#endif
|
||||
|
||||
if((dataToSign == NULL) || (sigLen == NULL) || (privKey == NULL)) {
|
||||
return RSA_ParamErr;
|
||||
}
|
||||
#if RSA_SIG_SHARE_GIANT
|
||||
if(signBuffer == NULL) {
|
||||
return RSA_ParamErr;
|
||||
}
|
||||
#else
|
||||
if(sig == NULL) {
|
||||
return RSA_ParamErr;
|
||||
}
|
||||
localGiantAlloc(&powermodScratch);
|
||||
#endif /* RSA_SIG_SHARE_GIANT */
|
||||
|
||||
GI_CHECK_SP("RSA_Sign");
|
||||
localGiantAlloc(&ptSigGiant);
|
||||
|
||||
rsaEnsurePrivRecip(privKey);
|
||||
modSize = ((bitlen(&privKey->p.g) + bitlen(&privKey->q.g)) + 7) / 8;
|
||||
switch(padding) {
|
||||
case RP_None:
|
||||
rtn = rsaAddNoPadding(dataToSign, dataToSignLen, &ptSigGiant.g);
|
||||
break;
|
||||
|
||||
#if RSA_PADDING_PKCS1_ENABLE
|
||||
case RP_PKCS1:
|
||||
rtn = rsaAddPkcs1Padding(dataToSign, dataToSignLen,
|
||||
modSize, RSA_PKCS1_PAD_SIGN,
|
||||
NULL, /* no RNG for signing */
|
||||
&ptSigGiant.g);
|
||||
break;
|
||||
#endif /* RSA_PADDING_PKCS1_ENABLE */
|
||||
|
||||
default:
|
||||
rtn = RSA_Unimplemented;
|
||||
break;
|
||||
}
|
||||
if(rtn) {
|
||||
rsaDebug1("RSA_Sign: AddPadding returned %s\n", rsaStatusStr(rtn));
|
||||
goto errOut;
|
||||
}
|
||||
|
||||
#if RSA_SIG_SHARE_GIANT
|
||||
/*
|
||||
* We init this. Not caller, not powermodCRT. But not before
|
||||
* we're done with the signature buffer, which could be the same
|
||||
* as dataToSign.
|
||||
*/
|
||||
localGiantAlloc(&signBuffer->g);
|
||||
#endif /* RSA_SIG_SHARE_GIANT */
|
||||
|
||||
/* sig := (ptext ^ d) mod n */
|
||||
showGiant("sign ptGiant", &ptSigGiant.g);
|
||||
powermodCRT(&ptSigGiant.g,
|
||||
&privKey->p.g, &privKey->pRecip.g,
|
||||
&privKey->q.g, &privKey->qRecip.g,
|
||||
&privKey->dp.g, &privKey->dq.g,
|
||||
&privKey->qInv.g,
|
||||
#if RSA_SIG_SHARE_GIANT
|
||||
&signBuffer->g.g,
|
||||
#else
|
||||
&powermodScratch.g,
|
||||
#endif
|
||||
&ptSigGiant.g);
|
||||
showGiant("sign sig ", &ptSigGiant.g);
|
||||
|
||||
#if RSA_SIG_SHARE_GIANT
|
||||
/* our sigLen is not IN/OUT, but the arg to serializeGiant is */
|
||||
*sigLen = sizeof(signBuffer->signature);
|
||||
grtn = serializeGiant(&ptSigGiant.g, signBuffer->signature, sigLen);
|
||||
#else
|
||||
grtn = serializeGiant(&ptSigGiant.g, sig, sigLen);
|
||||
#endif /* RSA_SIG_SHARE_GIANT */
|
||||
if(grtn) {
|
||||
rtn = giantStatusToRSA(grtn);
|
||||
rsaDebug1("RSA_Sign: serializeGiant returned %s\n", rsaStatusStr(rtn));
|
||||
}
|
||||
errOut:
|
||||
clearGiant(&ptSigGiant.g);
|
||||
return rtn;
|
||||
}
|
||||
#endif /* RSA_SIGN_ENABLE */
|
||||
|
||||
#if RSA_VERIFY_ENABLE
|
||||
|
||||
extern RSAStatus RSA_SigVerify(
|
||||
RSAPubGiantKey *pubKey, /* public key */
|
||||
RSAPadding padding, /* RP_None or RP_PKCS1 */
|
||||
const gi_uint8 *signedData, /* signature over this data */
|
||||
gi_uint16 signedDataLen, /* length of dataToSign */
|
||||
const gi_uint8 *sig, /* signature */
|
||||
gi_uint16 sigLen) /* length of signature */
|
||||
{
|
||||
RSAStatus rtn = RSA_Success;
|
||||
lgiant ptSigGiant; /* plain and decrypted signature */
|
||||
GIReturn grtn;
|
||||
|
||||
GI_CHECK_SP("RSA_SigVerify");
|
||||
GI_LOG_SP("RSA_SigVerify top");
|
||||
if((signedData == NULL) || (sig == NULL)) {
|
||||
return RSA_ParamErr;
|
||||
}
|
||||
if(pubKey == NULL) {
|
||||
return RSA_ParamErr;
|
||||
}
|
||||
|
||||
localGiantAlloc(&ptSigGiant);
|
||||
rsaEnsurePubRecip(pubKey);
|
||||
|
||||
/* signature --> giant */
|
||||
grtn = deserializeGiant(&ptSigGiant.g, sig, sigLen);
|
||||
if(grtn) {
|
||||
rtn = giantStatusToRSA(grtn);
|
||||
rsaDebug1("RSA_SigVerify: deserializeGiant (sig) returned %s\n",
|
||||
rsaStatusStr(rtn));
|
||||
return rtn;
|
||||
}
|
||||
|
||||
/* decrytped sig := (sig ^ e) mod n */
|
||||
/* powermodg allows base and result to reside in same giant */
|
||||
GI_LOG_SP("calling powermodg");
|
||||
showGiant("vfy ptGiant", &ptSigGiant.g);
|
||||
|
||||
powermodg(&ptSigGiant.g, &pubKey->e.g,
|
||||
&pubKey->n.g, &pubKey->recip.g,
|
||||
&ptSigGiant.g);
|
||||
|
||||
showGiant("vfy sig ", &ptSigGiant);
|
||||
|
||||
/* check and strip padding, verify data */
|
||||
switch(padding) {
|
||||
case RP_None:
|
||||
rtn = rsaCheckNoPaddingForSigVfy(&ptSigGiant.g, signedData, signedDataLen);
|
||||
break;
|
||||
|
||||
#if RSA_PADDING_PKCS1_ENABLE
|
||||
case RP_PKCS1:
|
||||
rtn = rsaCheckPkcs1PaddingForSigVfy(&ptSigGiant.g, signedData, signedDataLen);
|
||||
break;
|
||||
#endif /* RSA_PADDING_PKCS1_ENABLE */
|
||||
|
||||
default:
|
||||
rtn = RSA_Unimplemented;
|
||||
break;
|
||||
}
|
||||
if(rtn) {
|
||||
rsaDebug1("RSA_SigVerify: CheckPadding returned %s\n", rsaStatusStr(rtn));
|
||||
}
|
||||
|
||||
clearGiant(&ptSigGiant.g);
|
||||
return rtn;
|
||||
}
|
||||
#endif /* RSA_VERIFY_ENABLE */
|
||||
|
||||
#if RSA_ENCRYPT_ENABLE
|
||||
|
||||
extern RSAStatus RSA_Encrypt(
|
||||
RSAPubGiantKey *pubKey, /* public key */
|
||||
RSAPadding padding, /* RP_None, RP_PKCS1, RP_OAEP */
|
||||
RSARngCallback *rngCallback, /* required for RP_PKCS1, RP_OAEP */
|
||||
const gi_uint8 *plainText,
|
||||
gi_uint16 plainTextLen, /* length of plainText */
|
||||
gi_uint8 *cipherText,
|
||||
gi_uint16 *cipherTextLen) /* IN/OUT */
|
||||
{
|
||||
RSAStatus rtn = RSA_Success;
|
||||
lgiant ptCtGiant;
|
||||
GIReturn grtn;
|
||||
gi_uint16 modSize;
|
||||
|
||||
if((plainText == NULL) || (cipherText == NULL) || (cipherTextLen == NULL)) {
|
||||
return RSA_ParamErr;
|
||||
}
|
||||
if(pubKey == NULL) {
|
||||
return RSA_ParamErr;
|
||||
}
|
||||
|
||||
GI_CHECK_SP("RSA_Encrypt");
|
||||
localGiantAlloc(&ptCtGiant);
|
||||
rsaEnsurePubRecip(pubKey);
|
||||
|
||||
modSize = giantNumBytes(&pubKey->n.g);
|
||||
switch(padding) {
|
||||
case RP_None:
|
||||
rtn = rsaAddNoPadding(plainText, plainTextLen, &ptCtGiant.g);
|
||||
break;
|
||||
|
||||
#if RSA_PADDING_PKCS1_ENABLE
|
||||
case RP_PKCS1:
|
||||
rtn = rsaAddPkcs1Padding(plainText, plainTextLen,
|
||||
modSize, RSA_PKCS1_PAD_ENCRYPT,
|
||||
rngCallback,
|
||||
&ptCtGiant.g);
|
||||
break;
|
||||
#endif /* RSA_PADDING_PKCS1_ENABLE */
|
||||
|
||||
/* OEAP goes here eventually */
|
||||
|
||||
default:
|
||||
rtn = RSA_Unimplemented;
|
||||
break;
|
||||
}
|
||||
if(rtn) {
|
||||
rsaDebug1("RSA_Encrypt: AddPadding returned %s\n", rsaStatusStr(rtn));
|
||||
goto errOut;
|
||||
}
|
||||
|
||||
/* ctext := (ptext ^ e) mod n */
|
||||
/* ptext and ctext can share the same giant */
|
||||
powermodg(&ptCtGiant.g, &pubKey->e.g,
|
||||
&pubKey->n.g, &pubKey->recip.g,
|
||||
&ptCtGiant.g);
|
||||
|
||||
/* out to caller */
|
||||
grtn = serializeGiant(&ptCtGiant.g, cipherText, cipherTextLen);
|
||||
if(grtn) {
|
||||
rtn = giantStatusToRSA(grtn);
|
||||
rsaDebug1("RSA_Encrypt: serializeGiant returned %s\n", rsaStatusStr(rtn));
|
||||
}
|
||||
errOut:
|
||||
clearGiant(&ptCtGiant.g);
|
||||
return rtn;
|
||||
}
|
||||
#endif /* RSA_ENCRYPT_ENABLE */
|
||||
|
||||
#if RSA_DECRYPT_ENABLE
|
||||
|
||||
RSAStatus RSA_Decrypt(
|
||||
RSAPrivGiantKey *privKey, /* private key */
|
||||
RSAPadding padding, /* RP_None, RP_PKCS1, RP_OAEP */
|
||||
const gi_uint8 *cipherText,
|
||||
gi_uint16 cipherTextLen, /* length of cipherText */
|
||||
gi_uint8 *plainText,
|
||||
gi_uint16 *plainTextLen) /* IN/OUT */
|
||||
{
|
||||
RSAStatus rtn = RSA_Success;
|
||||
lgiant ptCtGiant;
|
||||
GIReturn grtn;
|
||||
lgiant powermodScratch;
|
||||
|
||||
if((plainText == NULL) || (cipherText == NULL) || (plainTextLen == NULL) || (privKey == NULL)) {
|
||||
return RSA_ParamErr;
|
||||
}
|
||||
|
||||
GI_CHECK_SP("RSA_Decrypt");
|
||||
localGiantAlloc(&ptCtGiant);
|
||||
localGiantAlloc(&powermodScratch);
|
||||
|
||||
rsaEnsurePrivRecip(privKey);
|
||||
|
||||
/* ciphertext --> giant */
|
||||
grtn = deserializeGiant(&ptCtGiant.g, cipherText, cipherTextLen);
|
||||
if(grtn) {
|
||||
rtn = giantStatusToRSA(grtn);
|
||||
rsaDebug1("RSA_Decrypt: deserializeGiant (sig) returned %s\n",
|
||||
rsaStatusStr(rtn));
|
||||
goto errOut;
|
||||
}
|
||||
|
||||
/* plaintext := (ciphertext ^ d) mod n */
|
||||
powermodCRT(&ptCtGiant.g,
|
||||
&privKey->p.g, &privKey->pRecip.g,
|
||||
&privKey->q.g, &privKey->qRecip.g,
|
||||
&privKey->dp.g, &privKey->dq.g,
|
||||
&privKey->qInv.g,
|
||||
&powermodScratch.g,
|
||||
&ptCtGiant.g);
|
||||
|
||||
/* check and strip padding */
|
||||
switch(padding) {
|
||||
case RP_None:
|
||||
rtn = rsaCheckNoPadding(&ptCtGiant.g, plainText, plainTextLen);
|
||||
break;
|
||||
|
||||
#if RSA_PADDING_PKCS1_ENABLE
|
||||
case RP_PKCS1:
|
||||
rtn = rsaCheckPkcs1Padding(&ptCtGiant.g, RSA_PKCS1_PAD_ENCRYPT,
|
||||
plainText, plainTextLen);
|
||||
break;
|
||||
#endif /* RSA_PADDING_PKCS1_ENABLE */
|
||||
|
||||
/* OAEP here */
|
||||
|
||||
default:
|
||||
rtn = RSA_Unimplemented;
|
||||
break;
|
||||
}
|
||||
if(rtn) {
|
||||
rsaDebug1("RSA_Decrypt: CheckPadding returned %s\n", rsaStatusStr(rtn));
|
||||
}
|
||||
|
||||
errOut:
|
||||
clearGiant(&ptCtGiant.g);
|
||||
return rtn;
|
||||
}
|
||||
|
||||
#endif /* RSA_DECRYPT_ENABLE */
|
||||
|
||||
@@ -0,0 +1,187 @@
|
||||
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
|
||||
|
||||
/*
|
||||
* libgRSA.h - public API for RSA library based on libGiants
|
||||
*/
|
||||
|
||||
#ifndef _LIBGRSA_LIBRSA_H_
|
||||
#define _LIBGRSA_LIBRSA_H_
|
||||
|
||||
#include <libgRSA/rsaTypes.h>
|
||||
#include <libgRSA/rsaGiantKey.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This file declares the main public functions in the libgRSA library.
|
||||
* Keys for all of these functions are expressed in "RSAGiantKey" format,
|
||||
* defined in rsaGiantKey.h. This is the native key format for this
|
||||
* library. RSAGiantKeys can be obtained in one of two ways:
|
||||
*
|
||||
* -- from DER-encoded, PKCS1-style key blobs, using the interface in
|
||||
* libgRSA_DER.h.
|
||||
* -- from raw byte strings representing individual key components, using
|
||||
* the interface in rsaRawKey.h.
|
||||
*/
|
||||
|
||||
/*
|
||||
* RSA_SIG_SHARE_GIANT, when true, is an optimization to reduce the stack
|
||||
* requirements when performing an RSA_Sign operation. When true, caller
|
||||
* allocates an RSASignBuffer union which contains both a sratch giant
|
||||
* for use by lower level code and the buffer into which a signature
|
||||
* will be written at the completion of RSA_Sign(). The input,
|
||||
* dataToSign, can also be in this RSASignBuffer (i.e., dataToSign
|
||||
* can equal RSASignBuffer.signature).
|
||||
*/
|
||||
#define RSA_SIG_SHARE_GIANT 0
|
||||
#if RSA_SIG_SHARE_GIANT
|
||||
|
||||
typedef union {
|
||||
lgiant g;
|
||||
gi_uint8 signature[MAX_PRIME_SIZE_BYTES];
|
||||
} RSASignBuffer;
|
||||
|
||||
#endif /* RSA_SIG_SHARE_GIANT */
|
||||
|
||||
|
||||
/*
|
||||
* Given a private key and data to sign, generate a digital signature.
|
||||
*
|
||||
* If the padding argument is RP_PKCS1, PKCS1 padding will be performed
|
||||
* prior to signing. If this argument is RP_None, the incoming data
|
||||
* will be signed "as is". (OAEP padding is not supported for signing.)
|
||||
* Note when PKCS1 padding is performed, the maximum length of data that
|
||||
* can be signed is RSAKey.nLen-11 where RSAKey.nLen is the length of
|
||||
* the modulus.
|
||||
*
|
||||
* NOTE: using RP_None will not work if the first byte of dataToSign
|
||||
* is zero; there is no way to verify leading zeroes as they got chopped
|
||||
* off during the calculation.
|
||||
|
||||
*
|
||||
* If you want a proper PKCS1 style signature, with DER encoding of the
|
||||
* incoming data - and the data is a SHA1 digest - use RSA_EncodeDigest
|
||||
* to format the data in an encoded DigestInfo struct before calling
|
||||
* this routine.
|
||||
*
|
||||
* If RSA_SIG_SHARE_GIANT is zero, caller allocates sig, the output buffer,
|
||||
* into which the signature will be written. This must be at least as large
|
||||
* as the key's modulus. On input, *sigLen is the size of the available buffer.
|
||||
* On output it's the size of the signature actually written to sig.
|
||||
*
|
||||
* If RSA_SIG_SHARE_GIANT is nonzero, caller allocates the signBuffer of
|
||||
* type RSASignBuffer; the signature will be written into
|
||||
* signBuffer->signature and *sigLen will equal the size of the
|
||||
* signature actually written to signBuffer->signature.
|
||||
*
|
||||
* When memory usage is a critical issue, note that the input buffer
|
||||
* (dataToSign) can be the same as the output buffer (sig, or
|
||||
* signBuffer->signature, depending on RSA_SIG_SHARE_GIANT).
|
||||
*
|
||||
* Returns an RSAStatus as described in libgRSA.h.
|
||||
*/
|
||||
|
||||
#if RSA_SIG_SHARE_GIANT
|
||||
|
||||
extern RSAStatus RSA_Sign(
|
||||
RSAPrivGiantKey *privKey, /* private key */
|
||||
RSAPadding padding, /* RP_None or RP_PKCS1 */
|
||||
const gi_uint8 *dataToSign, /* signature over this data */
|
||||
gi_uint16 dataToSignLen, /* length of dataToSign */
|
||||
RSASignBuffer *signBuffer, /* signature RETURNED here */
|
||||
gi_uint16 *sigLen); /* signature RETURNED here */
|
||||
|
||||
#else /* !RSA_SIG_SHARE_GIANT */
|
||||
|
||||
extern RSAStatus RSA_Sign(
|
||||
RSAPrivGiantKey *privKey, /* private key */
|
||||
RSAPadding padding, /* RP_None or RP_PKCS1 */
|
||||
const gi_uint8 *dataToSign, /* signature over this data */
|
||||
gi_uint16 dataToSignLen, /* length of dataToSign */
|
||||
gi_uint8 *sig, /* signature, RETURNED */
|
||||
gi_uint16 *sigLen); /* IN/OUT */
|
||||
|
||||
#endif /* RSA_SIG_SHARE_GIANT */
|
||||
|
||||
/*
|
||||
* Given a public key, data which has been signed, and a signature,
|
||||
* verify the signature.
|
||||
*
|
||||
* If the padding argument is RP_PKCS1, PKCS1 padding will be performed
|
||||
* prior to verification. If this argument is RP_None, the incoming data
|
||||
* will be verified "as is". (OAEP padding is not supported for verifying.)
|
||||
* Note when PKCS1 padding is performed, the maximum length of data that
|
||||
* can be signed and verified is RSAKey.nLen-11 where RSAKey.nLen is the
|
||||
* length of the modulus.
|
||||
*
|
||||
* If you are verifying a proper PKCS1 style signature, with DER encoding
|
||||
* of the incoming data - and the data is a SHA1 digest - use
|
||||
* DEREncodeSHA1DigestInfo to format the data in an encoded DigestInfo
|
||||
* struct before calling this routine.
|
||||
*
|
||||
* Returns an RSAStatus as described above.
|
||||
*/
|
||||
extern RSAStatus RSA_SigVerify(
|
||||
RSAPubGiantKey *pubKey, /* public key */
|
||||
RSAPadding padding, /* RP_None or RP_PKCS1 */
|
||||
const gi_uint8 *signedData, /* signature over this data */
|
||||
gi_uint16 signedDataLen, /* length of dataToSign */
|
||||
const gi_uint8 *sig, /* signature */
|
||||
gi_uint16 sigLen); /* length of signature */
|
||||
|
||||
/*
|
||||
* Encrypt a block of plaintext with a public key.
|
||||
* Resulting ciphertext is the same size as the key's modulus
|
||||
* (RSAKey.nLen) and is allocated by the caller.
|
||||
* The cipherTextLen argument, on input, specifies how much
|
||||
* space is available for the ciphertext; on return, it
|
||||
* is the actual number of ciphertext bytes written.
|
||||
*
|
||||
* When performing RP_PKCS1 or RP_OAEP padding, you must supply
|
||||
* a callback to a pseudorandom number generator via the rngFcn
|
||||
* argument.
|
||||
*
|
||||
* When memory usage is a critical issue, note that the input buffer
|
||||
* (plainText) can be the same as the output buffer (cipherText).
|
||||
*
|
||||
* Returns an RSAStatus as described above.
|
||||
*/
|
||||
extern RSAStatus RSA_Encrypt(
|
||||
RSAPubGiantKey *pubKey, /* public key */
|
||||
RSAPadding padding, /* RP_None, RP_PKCS1, RP_OAEP */
|
||||
RSARngCallback *rngCallback, /* required for RP_PKCS1, RP_OAEP */
|
||||
const gi_uint8 *plainText,
|
||||
gi_uint16 plainTextLen, /* length of plainText */
|
||||
gi_uint8 *cipherText,
|
||||
gi_uint16 *cipherTextLen); /* IN/OUT */
|
||||
|
||||
/*
|
||||
* Decrypt a block of ciphertext with a private key. The
|
||||
* ciphertext must be equal in length to the size of the
|
||||
* key's modulus. The plaintext buffer is allocated by
|
||||
* the caller' en entry, *plainTextLen is the size of the
|
||||
* available plaintext buffer; on return, it is the number
|
||||
* of plaintext bytes actually written.
|
||||
*
|
||||
* When memory usage is a critical issue, note that the input buffer
|
||||
* (cipherText) can be the same as the output buffer (plainText).
|
||||
*
|
||||
* Returns an RSAStatus as described above.
|
||||
*/
|
||||
extern RSAStatus RSA_Decrypt(
|
||||
RSAPrivGiantKey *privKey, /* private key */
|
||||
RSAPadding padding, /* RP_None, RP_PKCS1, RP_OAEP */
|
||||
const gi_uint8 *cipherText,
|
||||
gi_uint16 cipherTextLen, /* length of cipherText */
|
||||
gi_uint8 *plainText,
|
||||
gi_uint16 *plainTextLen); /* IN/OUT */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _LIBRSA_LIBRSA_H_ */
|
||||
|
||||
@@ -0,0 +1,440 @@
|
||||
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
|
||||
|
||||
/*
|
||||
* libgRSA_DER.c - DER encoding/decoding routines
|
||||
*/
|
||||
|
||||
#include <libgRSA/libgRSA_DER.h>
|
||||
#include <libgRSA/libgRSA_priv.h>
|
||||
#include <libgRSA/libgRSA_config.h>
|
||||
#include <libGiants/giantPlatform.h>
|
||||
#include <libGiants/giantExternal.h>
|
||||
#include <libGiants/giantMod.h>
|
||||
#include <libGiants/giantDebug.h>
|
||||
#include <libDER/DER_Keys.h>
|
||||
#include <libDER/asn1Types.h>
|
||||
|
||||
#ifndef RSA_PKCS1_KEY_ENABLE
|
||||
#error Please define RSA_PKCS1_KEY_ENABLE.
|
||||
#endif
|
||||
|
||||
#if RSA_PKCS1_KEY_ENABLE
|
||||
|
||||
#if RSA_PUB_KEY_ENABLE || RSA_PRIV_KEY_ENABLE
|
||||
|
||||
/* init an lgiant, fill it with incoming bytes */
|
||||
static RSAStatus rsaSetGiant(
|
||||
lgiant *g,
|
||||
DERItem *item)
|
||||
{
|
||||
localGiantAlloc(g);
|
||||
if(deserializeGiant(&g->g, item->data, item->length)) {
|
||||
return RSA_BadKeyData;
|
||||
}
|
||||
return RSA_Success;
|
||||
}
|
||||
|
||||
#endif /* RSA_PUB_KEY_ENABLE || RSA_PRIV_KEY_ENABLE */
|
||||
|
||||
/*
|
||||
* Decode PKCS1 form keys into RSA{Pub,Priv}GiantKey.
|
||||
*/
|
||||
|
||||
#if RSA_PUB_KEY_ENABLE
|
||||
|
||||
RSAStatus RSA_DecodePubKey(
|
||||
const unsigned char *pkcs1Key,
|
||||
gi_uint16 pkcs1KeyLen,
|
||||
RSAPubGiantKey *pubKey) /* RETURNED */
|
||||
{
|
||||
DERReturn drtn;
|
||||
DERItem keyItem = {(DERByte *)pkcs1Key, pkcs1KeyLen};
|
||||
DERRSAPubKeyPKCS1 decodedKey;
|
||||
RSAStatus rrtn;
|
||||
|
||||
GI_CHECK_SP("RSA_DecodePubKey");
|
||||
Bzero(pubKey, sizeof(*pubKey));
|
||||
drtn = DERParseSequence(&keyItem,
|
||||
DERNumRSAPubKeyPKCS1ItemSpecs, DERRSAPubKeyPKCS1ItemSpecs,
|
||||
&decodedKey, sizeof(decodedKey));
|
||||
if(drtn) {
|
||||
return RSA_BadKeyData;
|
||||
}
|
||||
|
||||
/* make_recip called lazily when the key is actually used */
|
||||
localGiantAlloc(&pubKey->recip);
|
||||
|
||||
rrtn = rsaSetGiant(&pubKey->n, &decodedKey.modulus);
|
||||
if(rrtn) {
|
||||
return rrtn;
|
||||
}
|
||||
return rsaSetGiant(&pubKey->e, &decodedKey.pubExponent);
|
||||
}
|
||||
|
||||
RSAStatus RSA_DecodeApplePubKey(
|
||||
const unsigned char *pkcs1Key,
|
||||
gi_uint16 pkcs1KeyLen,
|
||||
RSAPubGiantKey *pubKey) /* RETURNED */
|
||||
{
|
||||
DERReturn drtn;
|
||||
DERItem keyItem = {(DERByte *)pkcs1Key, pkcs1KeyLen};
|
||||
DERRSAPubKeyApple decodedKey;
|
||||
RSAStatus rrtn;
|
||||
|
||||
Bzero(pubKey, sizeof(*pubKey));
|
||||
drtn = DERParseSequence(&keyItem,
|
||||
DERNumRSAPubKeyAppleItemSpecs, DERRSAPubKeyAppleItemSpecs,
|
||||
&decodedKey, sizeof(decodedKey));
|
||||
if(drtn) {
|
||||
return RSA_BadKeyData;
|
||||
}
|
||||
|
||||
rrtn = rsaSetGiant(&pubKey->e, &decodedKey.pubExponent);
|
||||
if(rrtn) {
|
||||
return rrtn;
|
||||
}
|
||||
rrtn = rsaSetGiant(&pubKey->n, &decodedKey.modulus);
|
||||
if(rrtn) {
|
||||
return rrtn;
|
||||
}
|
||||
rrtn = rsaSetGiant(&pubKey->recip, &decodedKey.reciprocal);
|
||||
if(rrtn) {
|
||||
return rrtn;
|
||||
}
|
||||
return RSA_Success;
|
||||
}
|
||||
|
||||
#endif /* RSA_PUB_KEY_ENABLE */
|
||||
|
||||
#if RSA_PRIV_KEY_ENABLE
|
||||
|
||||
/* init an rsaSgiant, fill it with incoming bytes */
|
||||
static RSAStatus rsaSetSGiant(
|
||||
rsaSgiant *g,
|
||||
DERItem *item)
|
||||
{
|
||||
localSmallGiantAlloc(g);
|
||||
if(deserializeGiant(&g->g, item->data, item->length)) {
|
||||
return RSA_BadKeyData;
|
||||
}
|
||||
return RSA_Success;
|
||||
}
|
||||
|
||||
RSAStatus RSA_DecodePrivKey(
|
||||
const unsigned char *pkcs1Key,
|
||||
gi_uint16 pkcs1KeyLen,
|
||||
RSAPrivGiantKey *privKey) /* RETURNED */
|
||||
{
|
||||
DERReturn drtn;
|
||||
DERItem keyItem = {(DERByte *)pkcs1Key, pkcs1KeyLen};
|
||||
DERRSAPrivKeyCRT decodedKey;
|
||||
|
||||
Bzero(privKey, sizeof(*privKey));
|
||||
drtn = DERParseSequence(&keyItem,
|
||||
DERNumRSAPrivKeyCRTItemSpecs, DERRSAPrivKeyCRTItemSpecs,
|
||||
&decodedKey, sizeof(decodedKey));
|
||||
if(drtn) {
|
||||
return RSA_BadKeyData;
|
||||
}
|
||||
if(rsaSetSGiant(&privKey->p, &decodedKey.p)) {
|
||||
return RSA_BadKeyData;
|
||||
}
|
||||
if(rsaSetSGiant(&privKey->q, &decodedKey.q)) {
|
||||
return RSA_BadKeyData;
|
||||
}
|
||||
if(rsaSetSGiant(&privKey->dp, &decodedKey.dp)) {
|
||||
return RSA_BadKeyData;
|
||||
}
|
||||
if(rsaSetSGiant(&privKey->dq, &decodedKey.dq)) {
|
||||
return RSA_BadKeyData;
|
||||
}
|
||||
if(rsaSetSGiant(&privKey->qInv, &decodedKey.qInv)) {
|
||||
return RSA_BadKeyData;
|
||||
}
|
||||
|
||||
/* pRecip, qRecip evaluated lazily */
|
||||
localSmallGiantAlloc(&privKey->pRecip);
|
||||
localSmallGiantAlloc(&privKey->qRecip);
|
||||
|
||||
return RSA_Success;
|
||||
}
|
||||
|
||||
RSAStatus RSA_DecodeKeyPair(
|
||||
const unsigned char *pkcs1Key,
|
||||
gi_uint16 pkcs1KeyLen,
|
||||
RSAFullGiantKey *keyPair) /* RETURNED */
|
||||
{
|
||||
DERReturn drtn;
|
||||
DERItem keyItem = {(DERByte *)pkcs1Key, pkcs1KeyLen};
|
||||
DERRSAKeyPair decodedKey;
|
||||
|
||||
Bzero(keyPair, sizeof(*keyPair));
|
||||
drtn = DERParseSequence(&keyItem,
|
||||
DERNumRSAKeyPairItemSpecs, DERRSAKeyPairItemSpecs,
|
||||
&decodedKey, sizeof(decodedKey));
|
||||
if(drtn) {
|
||||
return RSA_BadKeyData;
|
||||
}
|
||||
if(rsaSetGiant(&keyPair->pub.n, &decodedKey.n)) {
|
||||
return RSA_BadKeyData;
|
||||
}
|
||||
if(rsaSetGiant(&keyPair->pub.e, &decodedKey.e)) {
|
||||
return RSA_BadKeyData;
|
||||
}
|
||||
if(rsaSetGiant(&keyPair->d, &decodedKey.d)) {
|
||||
return RSA_BadKeyData;
|
||||
}
|
||||
if(rsaSetSGiant(&keyPair->priv.p, &decodedKey.p)) {
|
||||
return RSA_BadKeyData;
|
||||
}
|
||||
if(rsaSetSGiant(&keyPair->priv.q, &decodedKey.q)) {
|
||||
return RSA_BadKeyData;
|
||||
}
|
||||
if(rsaSetSGiant(&keyPair->priv.dp, &decodedKey.dp)) {
|
||||
return RSA_BadKeyData;
|
||||
}
|
||||
if(rsaSetSGiant(&keyPair->priv.dq, &decodedKey.dq)) {
|
||||
return RSA_BadKeyData;
|
||||
}
|
||||
if(rsaSetSGiant(&keyPair->priv.qInv, &decodedKey.qInv)) {
|
||||
return RSA_BadKeyData;
|
||||
}
|
||||
|
||||
/* recip, pRecip, qRecip evaluated lazily */
|
||||
localGiantAlloc(&keyPair->pub.recip);
|
||||
localSmallGiantAlloc(&keyPair->priv.pRecip);
|
||||
localSmallGiantAlloc(&keyPair->priv.qRecip);
|
||||
|
||||
return RSA_Success;
|
||||
}
|
||||
|
||||
#endif /* RSA_PRIV_KEY_ENABLE */
|
||||
|
||||
#if RSA_KEY_GENERATE_ENABLE
|
||||
|
||||
#define RSA_MAX_GIANT_SIZE MAX_SERIALIZED_GIANT_SIZE(GIANT_LITTLE_DIGITS)
|
||||
|
||||
/*
|
||||
* Munge a giant (from e.g. a RSAFullGiantKey) into a gi_uint8 array
|
||||
* and then into a DERItem suitable for encoding.
|
||||
*/
|
||||
static RSAStatus rsaGiantToDerItem(
|
||||
giant g,
|
||||
gi_uint8 *cp,
|
||||
gi_uint16 cpLen,
|
||||
DERItem *derItem)
|
||||
{
|
||||
GIReturn grtn;
|
||||
gi_uint16 ioLen = cpLen;
|
||||
gi_uint16 dex;
|
||||
|
||||
/* serialize the giant into DER content */
|
||||
grtn = serializeGiant(g, cp, &ioLen);
|
||||
if(grtn) {
|
||||
return giantStatusToRSA(grtn);
|
||||
}
|
||||
|
||||
/* convert the result into a DERItem */
|
||||
derItem->data = cp;
|
||||
derItem->length = ioLen;
|
||||
|
||||
/* trim off leading zeroes (but leave one zero if that's all there is) */
|
||||
for(dex=0; dex<(ioLen-1); dex++) {
|
||||
if(*(derItem->data) != 0) {
|
||||
break;
|
||||
}
|
||||
derItem->data++;
|
||||
derItem->length--;
|
||||
}
|
||||
return RSA_Success;
|
||||
}
|
||||
|
||||
#if RSA_PUB_KEY_ENABLE
|
||||
|
||||
/* DER encode a public key, PKCS1 format */
|
||||
RSAStatus RSA_EncodePubKey(
|
||||
RSAPubGiantKey *giantKey,
|
||||
gi_uint8 *pkcs1Key, /* data written here */
|
||||
gi_uint32 *inOutLen) /* IN/OUT */
|
||||
{
|
||||
DERRSAPubKeyPKCS1 derKey;
|
||||
DERReturn drtn;
|
||||
RSAStatus rrtn;
|
||||
DERByte *der = pkcs1Key;
|
||||
DERSize ioLen = *inOutLen;
|
||||
|
||||
/* serialized giant byte arrays */
|
||||
gi_uint8 nChars[RSA_MAX_GIANT_SIZE];
|
||||
gi_uint8 eChars[RSA_MAX_GIANT_SIZE];
|
||||
|
||||
/* giants --> DERItems */
|
||||
rrtn = rsaGiantToDerItem(&giantKey->n.g, nChars, RSA_MAX_GIANT_SIZE,
|
||||
&derKey.modulus);
|
||||
if(rrtn) {
|
||||
return rrtn;
|
||||
}
|
||||
rrtn = rsaGiantToDerItem(&giantKey->e.g, eChars, RSA_MAX_GIANT_SIZE,
|
||||
&derKey.pubExponent);
|
||||
if(rrtn) {
|
||||
return rrtn;
|
||||
}
|
||||
|
||||
/* encode */
|
||||
drtn = DEREncodeSequence(ASN1_CONSTR_SEQUENCE,
|
||||
&derKey,
|
||||
DERNumRSAPubKeyPKCS1ItemSpecs, DERRSAPubKeyPKCS1ItemSpecs,
|
||||
der,
|
||||
&ioLen);
|
||||
if(drtn) {
|
||||
return derStatusToRSA(drtn);
|
||||
}
|
||||
|
||||
/* success */
|
||||
*inOutLen = ioLen;
|
||||
return RSA_Success;
|
||||
}
|
||||
|
||||
/* DER encode a public key, custom (to this library) format with reciprocal */
|
||||
RSAStatus RSA_EncodeApplePubKey(
|
||||
RSAPubGiantKey *giantKey,
|
||||
gi_uint8 *pubKey, /* data written here */
|
||||
gi_uint32 *inOutLen) /* IN/OUT */
|
||||
{
|
||||
DERRSAPubKeyApple derKey;
|
||||
DERReturn drtn;
|
||||
RSAStatus rrtn;
|
||||
DERByte *der = pubKey;
|
||||
DERSize ioLen = *inOutLen;
|
||||
bgiant recip;
|
||||
|
||||
/* serialized giant byte arrays */
|
||||
gi_uint8 nChars[RSA_MAX_GIANT_SIZE];
|
||||
gi_uint8 rChars[RSA_MAX_GIANT_SIZE];
|
||||
gi_uint8 eChars[RSA_MAX_GIANT_SIZE];
|
||||
|
||||
/* calculate the reciprocal */
|
||||
localBigGiantAlloc(&recip);
|
||||
make_recip(&giantKey->n.g, &recip.g);
|
||||
|
||||
/* giants --> DERItems */
|
||||
rrtn = rsaGiantToDerItem(&giantKey->n.g, nChars, RSA_MAX_GIANT_SIZE,
|
||||
&derKey.modulus);
|
||||
if(rrtn) {
|
||||
return rrtn;
|
||||
}
|
||||
rrtn = rsaGiantToDerItem(&recip.g, rChars, RSA_MAX_GIANT_SIZE,
|
||||
&derKey.reciprocal);
|
||||
if(rrtn) {
|
||||
return rrtn;
|
||||
}
|
||||
rrtn = rsaGiantToDerItem(&giantKey->e.g, eChars, RSA_MAX_GIANT_SIZE,
|
||||
&derKey.pubExponent);
|
||||
if(rrtn) {
|
||||
return rrtn;
|
||||
}
|
||||
|
||||
/* encode */
|
||||
drtn = DEREncodeSequence(ASN1_CONSTR_SEQUENCE,
|
||||
&derKey,
|
||||
DERNumRSAPubKeyAppleItemSpecs, DERRSAPubKeyAppleItemSpecs,
|
||||
der,
|
||||
&ioLen);
|
||||
if(drtn) {
|
||||
return derStatusToRSA(drtn);
|
||||
}
|
||||
|
||||
/* success */
|
||||
*inOutLen = ioLen;
|
||||
return RSA_Success;
|
||||
}
|
||||
|
||||
#endif /* RSA_PUB_KEY_ENABLE */
|
||||
|
||||
#if RSA_PRIV_KEY_ENABLE
|
||||
|
||||
/*
|
||||
* Create a PKCS1-formattted private key given a RSAFullGiantKey.
|
||||
* The inOutLen param contains the number of bytes available in
|
||||
* *pkcs1Key on entry, adn contains the number of bytes actually
|
||||
* written to *pkcs1Key on successful return.
|
||||
*/
|
||||
RSAStatus RSA_EncodeKeyPair(
|
||||
RSAFullGiantKey *keyPair,
|
||||
gi_uint8 *pkcs1Key, /* data written here */
|
||||
gi_uint32 *inOutLen) /* IN/OUT */
|
||||
{
|
||||
DERRSAKeyPair derKey;
|
||||
DERReturn drtn;
|
||||
RSAStatus rrtn;
|
||||
DERByte *der = pkcs1Key;
|
||||
DERSize ioLen = *inOutLen;
|
||||
DERByte version = 0;
|
||||
|
||||
/* serialized giant byte arrays */
|
||||
gi_uint8 nChars[RSA_MAX_GIANT_SIZE];
|
||||
gi_uint8 eChars[RSA_MAX_GIANT_SIZE];
|
||||
gi_uint8 dChars[RSA_MAX_GIANT_SIZE];
|
||||
gi_uint8 pChars[RSA_MAX_GIANT_SIZE];
|
||||
gi_uint8 qChars[RSA_MAX_GIANT_SIZE];
|
||||
gi_uint8 dpChars[RSA_MAX_GIANT_SIZE];
|
||||
gi_uint8 dqChars[RSA_MAX_GIANT_SIZE];
|
||||
gi_uint8 qInvChars[RSA_MAX_GIANT_SIZE];
|
||||
|
||||
derKey.version.data = &version;
|
||||
derKey.version.length = 1;
|
||||
|
||||
/* giants --> DERItems */
|
||||
rrtn = rsaGiantToDerItem(&keyPair->pub.n.g, nChars, RSA_MAX_GIANT_SIZE, &derKey.n);
|
||||
if(rrtn) {
|
||||
return rrtn;
|
||||
}
|
||||
rrtn = rsaGiantToDerItem(&keyPair->pub.e.g, eChars, RSA_MAX_GIANT_SIZE, &derKey.e);
|
||||
if(rrtn) {
|
||||
return rrtn;
|
||||
}
|
||||
rrtn = rsaGiantToDerItem(&keyPair->d.g, dChars, RSA_MAX_GIANT_SIZE, &derKey.d);
|
||||
if(rrtn) {
|
||||
return rrtn;
|
||||
}
|
||||
rrtn = rsaGiantToDerItem(&keyPair->priv.p.g, pChars, RSA_MAX_GIANT_SIZE, &derKey.p);
|
||||
if(rrtn) {
|
||||
return rrtn;
|
||||
}
|
||||
rrtn = rsaGiantToDerItem(&keyPair->priv.q.g, qChars, RSA_MAX_GIANT_SIZE, &derKey.q);
|
||||
if(rrtn) {
|
||||
return rrtn;
|
||||
}
|
||||
rrtn = rsaGiantToDerItem(&keyPair->priv.dp.g, dpChars, RSA_MAX_GIANT_SIZE, &derKey.dp);
|
||||
if(rrtn) {
|
||||
return rrtn;
|
||||
}
|
||||
rrtn = rsaGiantToDerItem(&keyPair->priv.dq.g, dqChars, RSA_MAX_GIANT_SIZE, &derKey.dq);
|
||||
if(rrtn) {
|
||||
return rrtn;
|
||||
}
|
||||
rrtn = rsaGiantToDerItem(&keyPair->priv.qInv.g, qInvChars, RSA_MAX_GIANT_SIZE, &derKey.qInv);
|
||||
if(rrtn) {
|
||||
return rrtn;
|
||||
}
|
||||
|
||||
/* encode */
|
||||
drtn = DEREncodeSequence(ASN1_CONSTR_SEQUENCE,
|
||||
&derKey,
|
||||
DERNumRSAKeyPairItemSpecs, DERRSAKeyPairItemSpecs,
|
||||
der,
|
||||
&ioLen);
|
||||
if(drtn) {
|
||||
return derStatusToRSA(drtn);
|
||||
}
|
||||
|
||||
/* success */
|
||||
*inOutLen = ioLen;
|
||||
return RSA_Success;
|
||||
}
|
||||
|
||||
#endif /* RSA_PRIV_KEY_ENABLE */
|
||||
|
||||
#endif /* RSA_KEY_GENERATE_ENABLE */
|
||||
|
||||
#endif /* RSA_PKCS1_KEY_ENABLE */
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
|
||||
|
||||
/*
|
||||
* libgRSA_DER.h - DER encoding/decoding routines
|
||||
*/
|
||||
|
||||
#ifndef _LIBGRSA_LIBRSA_DER_H_
|
||||
#define _LIBGRSA_LIBRSA_DER_H_
|
||||
|
||||
#include <libgRSA/libgRSA.h>
|
||||
#include <libgRSA/libgRSA_config.h>
|
||||
#include <libGiants/giantPlatform.h>
|
||||
#include <libDER/DER_Encode.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Decode PKCS1 form keys into RSA{Pub,Priv}GiantKey.
|
||||
*/
|
||||
RSAStatus RSA_DecodePubKey(
|
||||
const unsigned char *pkcs1Key,
|
||||
gi_uint16 pkcs1KeyLen,
|
||||
RSAPubGiantKey *pubKey); /* RETURNED */
|
||||
|
||||
RSAStatus RSA_DecodePrivKey(
|
||||
const unsigned char *pkcs1Key,
|
||||
gi_uint16 pkcs1KeyLen,
|
||||
RSAPrivGiantKey *privKey); /* RETURNED */
|
||||
|
||||
RSAStatus RSA_DecodeKeyPair(
|
||||
const unsigned char *pkcs1Key,
|
||||
gi_uint16 pkcs1KeyLen,
|
||||
RSAFullGiantKey *keyPair); /* RETURNED */
|
||||
|
||||
/*
|
||||
* Decode an custom (to this library) public key with reciprocal.
|
||||
*/
|
||||
RSAStatus RSA_DecodeApplePubKey(
|
||||
const unsigned char *aplePubKey,
|
||||
gi_uint16 applePubKeyLen,
|
||||
RSAPubGiantKey *pubKey); /* RETURNED */
|
||||
|
||||
/*
|
||||
* Generated key pair encoding support.
|
||||
*/
|
||||
|
||||
#define RSA_HALF_SIZE(keySizeInBytes) ((keySizeInBytes + 1) / 2)
|
||||
|
||||
/*
|
||||
* To allocate space on the stack for encoded public and private keys,
|
||||
* use these macros to determine the max size needed. They are conservative;
|
||||
* they will almost certainly allocate more space than you really
|
||||
* end up needing for the encoded keys.
|
||||
*/
|
||||
#define RSA_ENCODED_PRIV_KEY_SIZE(keySizeInBytes) \
|
||||
DER_MAX_ENCODED_SIZE( \
|
||||
DER_MAX_ENCODED_SIZE(1) + /* version */ \
|
||||
DER_MAX_ENCODED_SIZE(keySizeInBytes) + /* n */ \
|
||||
DER_MAX_ENCODED_SIZE(keySizeInBytes) + /* e */ \
|
||||
DER_MAX_ENCODED_SIZE(keySizeInBytes) + /* d */ \
|
||||
DER_MAX_ENCODED_SIZE(RSA_HALF_SIZE(keySizeInBytes)) + /* p */ \
|
||||
DER_MAX_ENCODED_SIZE(RSA_HALF_SIZE(keySizeInBytes)) + /* q */ \
|
||||
DER_MAX_ENCODED_SIZE(RSA_HALF_SIZE(keySizeInBytes)) + /* dp */ \
|
||||
DER_MAX_ENCODED_SIZE(RSA_HALF_SIZE(keySizeInBytes)) + /* dq */ \
|
||||
DER_MAX_ENCODED_SIZE(RSA_HALF_SIZE(keySizeInBytes))) /* qInv */
|
||||
|
||||
#define RSA_ENCODED_PUB_KEY_SIZE(keySizeInBytes) \
|
||||
DER_MAX_ENCODED_SIZE( \
|
||||
DER_MAX_ENCODED_SIZE(keySizeInBytes) + /* n */ \
|
||||
DER_MAX_ENCODED_SIZE(keySizeInBytes)) /* e */
|
||||
|
||||
#define RSA_ENCODED_APPLE_PUB_KEY_SIZE(keySizeInBytes) \
|
||||
DER_MAX_ENCODED_SIZE( \
|
||||
DER_MAX_ENCODED_SIZE(keySizeInBytes) + /* n */ \
|
||||
DER_MAX_ENCODED_SIZE(keySizeInBytes) + /* recip */ \
|
||||
GIANT_BYTES_PER_DIGIT + /* recip: one extra digit */ \
|
||||
DER_MAX_ENCODED_SIZE(keySizeInBytes)) /* e */
|
||||
|
||||
/*
|
||||
* Create PKCS1-formatted public key given a RSAFullGiantKey.
|
||||
* The inOutLen param contains the number of bytes available in
|
||||
* *pkcs1Key on entry, adn contains the number of bytes actually
|
||||
* written to *pkcs1Key on successful return.
|
||||
*/
|
||||
RSAStatus RSA_EncodePubKey(
|
||||
RSAPubGiantKey *giantKey,
|
||||
gi_uint8 *pkcs1Key, /* data written here */
|
||||
gi_uint32 *inOutLen); /* IN/OUT */
|
||||
|
||||
/*
|
||||
* Create a PKCS1-formattted private key given a RSAFullGiantKey.
|
||||
* The inOutLen param contains the number of bytes available in
|
||||
* *pkcs1Key on entry, adn contains the number of bytes actually
|
||||
* written to *pkcs1Key on successful return.
|
||||
*/
|
||||
RSAStatus RSA_EncodeKeyPair(
|
||||
RSAFullGiantKey *keyPair,
|
||||
gi_uint8 *pkcs1Key, /* data written here */
|
||||
gi_uint32 *inOutLen); /* IN/OUT */
|
||||
|
||||
/*
|
||||
* Create a custom (to this library) DER-encoded public key including
|
||||
* the reciprocal.
|
||||
* The inOutLen param contains the number of bytes available in
|
||||
* *pubKey on entry, adn contains the number of bytes actually
|
||||
* written to *pkcs1Key on successful return.
|
||||
*/
|
||||
RSAStatus RSA_EncodeApplePubKey(
|
||||
RSAPubGiantKey *giantKey,
|
||||
gi_uint8 *pubKey, /* data written here */
|
||||
gi_uint32 *inOutLen); /* IN/OUT */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _LIBGRSA_LIBRSA_DER_H_ */
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
|
||||
|
||||
/*
|
||||
* libgRSA_config.h - #defines controlling what features are enabled in a
|
||||
* given implementation of this library.
|
||||
*
|
||||
* Created Aug. 9 2005 by Doug Mitchell.
|
||||
*/
|
||||
|
||||
#ifndef _LIBGRSA_LIBRSA_CONFIG_H_
|
||||
#define _LIBGRSA_LIBRSA_CONFIG_H_
|
||||
|
||||
/* one flag for each basic RSA operation */
|
||||
#define RSA_SIGN_ENABLE 1
|
||||
#define RSA_VERIFY_ENABLE 1
|
||||
#define RSA_ENCRYPT_ENABLE 1
|
||||
#define RSA_DECRYPT_ENABLE 1
|
||||
|
||||
/* values inferred from above four flags - do not modify */
|
||||
#define RSA_SIGVFY_ENABLE (RSA_SIGN_ENABLE || RSA_VERIFY_ENABLE)
|
||||
#define RSA_ENCRDECR_ENABLE (RSA_ENCRYPT_ENABLE || RSA_DECRYPT_ENABLE)
|
||||
#define RSA_PUB_KEY_ENABLE (RSA_VERIFY_ENABLE || RSA_ENCRYPT_ENABLE)
|
||||
#define RSA_PRIV_KEY_ENABLE (RSA_SIGN_ENABLE || RSA_DECRYPT_ENABLE)
|
||||
|
||||
/*
|
||||
* Enables DER encoding of DigestInfo for proper PKCS1 signatures
|
||||
* This is always disabled if !RSA_SIGVFY_ENABLE.
|
||||
*/
|
||||
#if RSA_SIGVFY_ENABLE
|
||||
#define RSA_DER_DIGEST_ENABLE 1 /* your platform's value here */
|
||||
#else
|
||||
#define RSA_DER_DIGEST_ENABLE 0 /* hard coded - do not change */
|
||||
#endif
|
||||
|
||||
/* enable support for PKCS1 and OEAP padding */
|
||||
#define RSA_PADDING_PKCS1_ENABLE 1
|
||||
#define RSA_PADDING_OAEP_ENABLE 0 /* not supported yet */
|
||||
|
||||
/* enable support for PKCS1 format keys */
|
||||
#define RSA_PKCS1_KEY_ENABLE 1
|
||||
|
||||
/* enable support for raw keys (rsaRawKey.[ch]) */
|
||||
#define RSA_RAW_KEY_ENABLE 1
|
||||
|
||||
/* enable key pair generation */
|
||||
#define RSA_KEY_GENERATE_ENABLE 1
|
||||
|
||||
#endif /* _LIBGRSA_LIBRSA_CONFIG_H_ */
|
||||
@@ -0,0 +1,86 @@
|
||||
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
|
||||
|
||||
/*
|
||||
* libgRSA_priv.c - private libRSA routines.
|
||||
*
|
||||
* Created Aug. 10 2005 by Doug Mitchell.
|
||||
*/
|
||||
|
||||
#include <libgRSA/libgRSA_priv.h>
|
||||
|
||||
/* convert a libGiants GIReturn to our own RSAStatus */
|
||||
RSAStatus giantStatusToRSA(GIReturn grtn)
|
||||
{
|
||||
switch(grtn) {
|
||||
case GR_Success: return RSA_Success;
|
||||
case GR_IllegalArg: return RSA_ParamErr;
|
||||
case GR_Unimplemented: return RSA_Unimplemented;
|
||||
case GR_Internal: return RSA_InternalError;
|
||||
case GR_Overflow: return RSA_Overflow;
|
||||
default: return RSA_OtherError;
|
||||
}
|
||||
}
|
||||
|
||||
/* convert a libDER DERReturn to our own RSAStatus */
|
||||
RSAStatus derStatusToRSA(DERReturn drtn)
|
||||
{
|
||||
switch(drtn) {
|
||||
case DR_Success: return RSA_Success;
|
||||
case DR_ParamErr: return RSA_ParamErr;
|
||||
case DR_BufOverflow: return RSA_Overflow;
|
||||
case DR_Unimplemented: return RSA_Unimplemented;
|
||||
default: return RSA_BadKeyFormat;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
||||
#include <libGiantsUtils/GIReturnString.h>
|
||||
|
||||
/* be sure to update the mirrored copy in libgRSAUtils when this changes */
|
||||
const char *rsaStatusStr(RSAStatus rrtn)
|
||||
{
|
||||
static char unknownStr[100];
|
||||
|
||||
if(rrtn < RSA_RETURN_BASE) {
|
||||
if(rrtn == RSA_Success) {
|
||||
return "RSA_Success";
|
||||
}
|
||||
else {
|
||||
/* libGiants error */
|
||||
return GIReturnString((GIReturn)rrtn);
|
||||
}
|
||||
}
|
||||
switch(rrtn) {
|
||||
case RSA_BadKeyData:
|
||||
return "RSA_BadKeyData";
|
||||
case RSA_ParamErr:
|
||||
return "RSA_ParamErr";
|
||||
case RSA_IncompleteKey:
|
||||
return "RSA_IncompleteKey";
|
||||
case RSA_VerifyFail:
|
||||
return "RSA_VerifyFail";
|
||||
case RSA_BadSigFormat:
|
||||
return "RSA_BadSigFormat";
|
||||
case RSA_BadDataFormat:
|
||||
return "RSA_BadDataFormat";
|
||||
case RSA_BadKeyFormat:
|
||||
return "RSA_BadKeyFormat";
|
||||
case RSA_InternalError:
|
||||
return "RSA_InternalError";
|
||||
case RSA_Overflow:
|
||||
return "RSA_Overflow";
|
||||
case RSA_Unimplemented:
|
||||
return "RSA_Unimplemented";
|
||||
case RSA_IllegalKeySize:
|
||||
return "RSA_IllegalKeySize";
|
||||
case RSA_OtherError:
|
||||
return "RSA_OtherError";
|
||||
default:
|
||||
sprintf(unknownStr, "Unknown (%d)", rrtn);
|
||||
return unknownStr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif /* NDEBUG */
|
||||
@@ -0,0 +1,56 @@
|
||||
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
|
||||
|
||||
/*
|
||||
* libgRSA_priv.h - private libRSA routines.
|
||||
*
|
||||
* Created Aug. 10 2005 by Doug Mitchell.
|
||||
*/
|
||||
|
||||
#ifndef _LIBGRSA_RSA_PRIV_H_
|
||||
#define _LIBGRSA_RSA_PRIV_H_
|
||||
|
||||
#include <libgRSA/libgRSA.h>
|
||||
#include <libGiants/giantIntegers.h>
|
||||
#include <libDER/libDER.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* make sure NDEBUG is #define for deployment build! */
|
||||
#define NDEBUG
|
||||
#ifdef NDEBUG
|
||||
|
||||
#define rsaDebug(s)
|
||||
#define rsaDebug1(s, a)
|
||||
#define rsaDebug2(s, a, b)
|
||||
#define RSAASSERT(s)
|
||||
|
||||
#else /* !NDEBUG */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define rsaDebug(s) printf(s)
|
||||
#define rsaDebug1(s, a) printf(s, a)
|
||||
#define rsaDebug2(s, a, b) printf(s, a, b)
|
||||
|
||||
#define RSAASSERT(s) assert(s)
|
||||
|
||||
|
||||
#endif /* !NDEBUG */
|
||||
|
||||
/* convert a libGiants GIReturn to our own RSAStatus */
|
||||
extern RSAStatus giantStatusToRSA(GIReturn grtn);
|
||||
|
||||
/* convert a libDER DERReturn to our own RSAStatus */
|
||||
extern RSAStatus derStatusToRSA(DERReturn drtn);
|
||||
|
||||
/* convert an RSAStatus to a string (disabled for NDEBUG builds) */
|
||||
extern const char *rsaStatusStr(RSAStatus rrtn);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _LIBGRSA_RSA_PRIV_H_ */
|
||||
@@ -0,0 +1,38 @@
|
||||
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
|
||||
|
||||
/*
|
||||
* rsaGiantKey.c
|
||||
*
|
||||
* Created Aug. 9 2005 by Doug Mitchell.
|
||||
*/
|
||||
|
||||
#include <libgRSA/rsaGiantKey.h>
|
||||
#include <libGiants/giantIntegers.h>
|
||||
#include <libGiants/giantDebug.h>
|
||||
|
||||
/* call this after declaring a local lgiant and before using it */
|
||||
void localSmallGiantAlloc(rsaSgiant *g)
|
||||
{
|
||||
initGiant(&g->g, RSA_SMALL_GIANT_DIGITS, g->_n_);
|
||||
}
|
||||
|
||||
/* clear an RSA{Pub,Priv}GiantKey */
|
||||
void rsaClearPubGKey(
|
||||
RSAPubGiantKey *gKey)
|
||||
{
|
||||
Bzero(gKey, sizeof(*gKey));
|
||||
}
|
||||
|
||||
void rsaClearPrivGKey(
|
||||
RSAPrivGiantKey *gKey)
|
||||
{
|
||||
Bzero(gKey, sizeof(*gKey));
|
||||
}
|
||||
|
||||
void rsaClearFullGiantKey(
|
||||
RSAFullGiantKey *gKey)
|
||||
{
|
||||
Bzero(gKey, sizeof(*gKey));
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
|
||||
|
||||
/*
|
||||
* rsaGiantKey.h - internal format of RSA keys, constructors for them.
|
||||
*/
|
||||
|
||||
#ifndef _LIBGRSA_RSA_GIANT_KEY_H_
|
||||
#define _LIBGRSA_RSA_GIANT_KEY_H_
|
||||
|
||||
#include <libgRSA/libgRSA_config.h>
|
||||
#include <libGiants/giantIntegers.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* A custom "small" giant used to represent some individual fields in a
|
||||
* RSAFullGiantKey. These fields are typically half the size of the
|
||||
* modulus. We use MAX_PRIME_SIZE/2 + 1 digits for these.
|
||||
*/
|
||||
#define RSA_SMALL_GIANT_DIGITS ((MAX_PRIME_SIZE_DIGITS + 3) / 2)
|
||||
|
||||
typedef struct {
|
||||
giantStruct g;
|
||||
giantDigit _n_[RSA_SMALL_GIANT_DIGITS];
|
||||
} rsaSmallGiantStruct;
|
||||
|
||||
typedef rsaSmallGiantStruct rsaSgiant; /* for heap allocation */
|
||||
|
||||
/* call this after declaring a local lgiant and before using it */
|
||||
extern void localSmallGiantAlloc(rsaSgiant *g);
|
||||
|
||||
/* RSA public key form native to this library */
|
||||
typedef struct {
|
||||
lgiant e; /* public exponent */
|
||||
lgiant n; /* modulus */
|
||||
lgiant recip; /* reciprocal of n */
|
||||
} RSAPubGiantKey;
|
||||
|
||||
/* RSA private key form native to this library */
|
||||
typedef struct {
|
||||
rsaSgiant p;
|
||||
rsaSgiant q;
|
||||
rsaSgiant dp;
|
||||
rsaSgiant dq;
|
||||
rsaSgiant qInv;
|
||||
|
||||
/* reciprocals of p and q */
|
||||
rsaSgiant pRecip;
|
||||
rsaSgiant qRecip;
|
||||
} RSAPrivGiantKey;
|
||||
|
||||
/*
|
||||
* A full RSA key pair.
|
||||
*/
|
||||
typedef struct {
|
||||
RSAPubGiantKey pub;
|
||||
lgiant d; /* private exponent */
|
||||
RSAPrivGiantKey priv;
|
||||
} RSAFullGiantKey;
|
||||
|
||||
/* clear an RSA*GiantKey */
|
||||
void rsaClearPubGKey(
|
||||
RSAPubGiantKey *gKey);
|
||||
|
||||
void rsaClearPrivGKey(
|
||||
RSAPrivGiantKey *gKey);
|
||||
|
||||
void rsaClearFullGiantKey(
|
||||
RSAFullGiantKey *gKey);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _LIBGRSA_RSA_GIANT_KEY_H_ */
|
||||
|
||||
@@ -0,0 +1,532 @@
|
||||
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
|
||||
|
||||
/*
|
||||
* rsaPadding.c - PKCS1 and OAEP padding support.
|
||||
*
|
||||
* Created Aug. 10 2005 by Doug Mitchell.
|
||||
*/
|
||||
|
||||
#include <libgRSA/rsaPadding.h>
|
||||
#include <libgRSA/libgRSA_config.h>
|
||||
#include <libgRSA/libgRSA_priv.h>
|
||||
#include <libGiants/giantExternal.h>
|
||||
#include <libGiants/giantDebug.h>
|
||||
#include <AssertMacros.h>
|
||||
|
||||
/*
|
||||
* RP_None padding routines - just check length and convert between
|
||||
* byte array and giant
|
||||
*/
|
||||
RSAStatus rsaAddNoPadding(
|
||||
const unsigned char *plainText,
|
||||
gi_uint16 plainTextLen,
|
||||
giant result) /* RETURNED */
|
||||
{
|
||||
GIReturn rtn = deserializeGiant(result, plainText, plainTextLen);
|
||||
return giantStatusToRSA(rtn);
|
||||
}
|
||||
|
||||
RSAStatus rsaCheckNoPadding(
|
||||
giant decryptResult,
|
||||
unsigned char *plainText, /* data RETURNED here */
|
||||
gi_uint16 *plainTextLen) /* IN/OUT */
|
||||
{
|
||||
GIReturn rtn = serializeGiant(decryptResult,
|
||||
(gi_uint8 *)plainText, plainTextLen);
|
||||
return giantStatusToRSA(rtn);
|
||||
}
|
||||
|
||||
#if RSA_VERIFY_ENABLE
|
||||
|
||||
/*
|
||||
* Decrement digit ptr and byte index thru a giant's n[],
|
||||
* going from m.s. byte to l.s. byte.
|
||||
* -- n[0] is the l.s. digit of a giant
|
||||
* -- (n[0] & 0xff) is the l.s. byte of that digit
|
||||
*/
|
||||
static inline void decrGiantPtrs(
|
||||
giantDigit **digitPtr,
|
||||
gi_uint8 *byteDex)
|
||||
{
|
||||
if(*byteDex == 0) {
|
||||
/* roll to m.s. byte of next l.s. digit */
|
||||
(*digitPtr)--;
|
||||
*byteDex = GIANT_BYTES_PER_DIGIT - 1;
|
||||
}
|
||||
else {
|
||||
(*byteDex)--;
|
||||
}
|
||||
}
|
||||
|
||||
/* fetch specified byte from giant's n[] array */
|
||||
static inline gi_uint8 getGiantByte(
|
||||
giantDigit *digitPtr,
|
||||
gi_uint8 byteDex)
|
||||
{
|
||||
giantDigit digit = *digitPtr;
|
||||
digit >>= (byteDex * 8);
|
||||
return (gi_uint8)digit;
|
||||
}
|
||||
|
||||
/*
|
||||
* How many bytes are left between current digit/byte markers and
|
||||
* the start of the giant's data?
|
||||
*/
|
||||
static inline gi_size bytesLeftInGiant(
|
||||
giant g,
|
||||
giantDigit *digitPtr,
|
||||
gi_uint8 byteDex)
|
||||
{
|
||||
GIASSERT(digitPtr >= g->n);
|
||||
return ((digitPtr - g->n) * GIANT_BYTES_PER_DIGIT) + byteDex + 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Specialized "no padding" check for signature verify operation.
|
||||
* We don't deserialize the decrypted giant; we do a byte-for-
|
||||
* byte compare of the expected decrypted value against memory
|
||||
* passed in to us, in-place in the decrypted giant.
|
||||
* This saves two stack-allocated byte arrays, each of
|
||||
* MAX_PRIME_SIZE_BYTES - one here, and one in RSA_SigVerify().
|
||||
*
|
||||
* NOTE: using "no padding" option will not work if the first byte
|
||||
* (the m.s. byte of the decryptResult giant) is zero; there is
|
||||
* no way to verify leading zeroes as they got chopped off during
|
||||
* the calculation.
|
||||
*/
|
||||
RSAStatus rsaCheckNoPaddingForSigVfy(
|
||||
giant decryptResult,
|
||||
const unsigned char *expectPlainText,
|
||||
gi_uint16 expectPlainTextLen)
|
||||
{
|
||||
unsigned dex;
|
||||
giantDigit *digitPtr;
|
||||
gi_uint8 byteDex;
|
||||
gi_uint8 giantByte;
|
||||
gi_size bytesLeft;
|
||||
|
||||
if((expectPlainText == NULL) || (decryptResult == NULL)) {
|
||||
return RSA_InternalError;
|
||||
}
|
||||
if(expectPlainTextLen > MAX_PRIME_SIZE_BYTES) {
|
||||
return RSA_Overflow;
|
||||
}
|
||||
if(decryptResult->sign == 0) {
|
||||
if(expectPlainTextLen == 0) {
|
||||
/* Well OK */
|
||||
return RSA_Success;
|
||||
}
|
||||
else {
|
||||
rsaDebug("rsaCheckNoPaddingForSigVfy: empty decryptResult\n");
|
||||
return RSA_VerifyFail;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Prepare for scanning thru giant data, starting at the m.s. byte of the
|
||||
* m.s. digit.
|
||||
*/
|
||||
digitPtr = &decryptResult->n[decryptResult->sign - 1];
|
||||
byteDex = GIANT_BYTES_PER_DIGIT - 1;
|
||||
bytesLeft = bytesLeftInGiant(decryptResult, digitPtr, byteDex);
|
||||
GIASSERT(bytesLeft != 0);
|
||||
|
||||
/* find first non-zero byte */
|
||||
for(;;) {
|
||||
giantByte = getGiantByte(digitPtr, byteDex);
|
||||
if(giantByte != 0) {
|
||||
break;
|
||||
}
|
||||
decrGiantPtrs(&digitPtr, &byteDex);
|
||||
if(--bytesLeft == 0) {
|
||||
rsaDebug("rsaCheckNoPaddingForSigVfy: non nonzero data found\n");
|
||||
return RSA_VerifyFail;
|
||||
}
|
||||
}
|
||||
|
||||
if(bytesLeft != expectPlainTextLen) {
|
||||
rsaDebug("rsaCheckNoPaddingForSigVfy: length mismatch\n");
|
||||
return RSA_VerifyFail;
|
||||
}
|
||||
|
||||
for(dex=0; dex<bytesLeft; dex++) {
|
||||
giantByte = getGiantByte(digitPtr, byteDex);
|
||||
decrGiantPtrs(&digitPtr, &byteDex);
|
||||
if(giantByte != expectPlainText[dex]) {
|
||||
rsaDebug("rsaCheckNoPaddingForSigVfy: data miscompare\n");
|
||||
return RSA_VerifyFail;
|
||||
}
|
||||
}
|
||||
|
||||
/* TA DA */
|
||||
return RSA_Success;
|
||||
|
||||
}
|
||||
|
||||
#endif /* RSA_VERIFY_ENABLE */
|
||||
|
||||
#if RSA_PADDING_PKCS1_ENABLE
|
||||
|
||||
#define PKCS1_MIN_PAD_LEN 11 /* minumum length of padding */
|
||||
|
||||
#if RSA_SIGN_ENABLE || RSA_ENCRYPT_ENABLE
|
||||
|
||||
/* Write randSize bytes of nonzero data into randBuf. */
|
||||
static RSAStatus nonZeroRandom(
|
||||
RSARngCallback *rngCallback,
|
||||
gi_uint8 *randBuf, /* random data goes here */
|
||||
gi_uint16 randSize) /* byte count */
|
||||
{
|
||||
RSAStatus rstatus = RSA_Success;
|
||||
|
||||
gi_uint8 scratch[randSize];
|
||||
gi_uint16 dix, six = randSize;
|
||||
for (dix = 0; dix < randSize; ++dix) {
|
||||
for (;;) {
|
||||
if (six >= randSize) {
|
||||
require_noerr(rstatus = rngCallback(scratch, randSize), errOut);
|
||||
six = 0;
|
||||
}
|
||||
|
||||
gi_uint8 b = scratch[six++];
|
||||
if (b) {
|
||||
randBuf[dix] = b;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
errOut:
|
||||
/* Clear out scratch cause we like being paranoid. */
|
||||
Bzero(scratch, randSize);
|
||||
return rstatus;
|
||||
}
|
||||
|
||||
/*
|
||||
* Given plaintext or data to be signed, add PKCS1 padding and place
|
||||
* the result in a giant.
|
||||
*/
|
||||
RSAStatus rsaAddPkcs1Padding(
|
||||
const unsigned char *plainText,
|
||||
gi_uint16 plainTextLen,
|
||||
gi_uint16 totalLength, /* intended total length */
|
||||
unsigned char padMarker, /* RSA_PKCS1_PAD_{SIGN,ENCRYPT} */
|
||||
RSARngCallback *rngCallback, /* required for RP_PKCS1, RP_OAEP */
|
||||
giant result)
|
||||
{
|
||||
unsigned char giantBytes[MAX_PRIME_SIZE_BYTES];
|
||||
unsigned char *cp = giantBytes;
|
||||
unsigned dex;
|
||||
GIReturn grtn;
|
||||
RSAStatus rrtn = RSA_Success;
|
||||
unsigned psLen; /* length of variable length padding string */
|
||||
|
||||
if((plainText == NULL) || (result == NULL)) {
|
||||
return RSA_InternalError;
|
||||
}
|
||||
if(totalLength > MAX_PRIME_SIZE_BYTES) {
|
||||
return RSA_Overflow;
|
||||
}
|
||||
if(plainTextLen > (totalLength - PKCS1_MIN_PAD_LEN)) {
|
||||
rsaDebug("rsaAddPkcs1Padding: insuffient space for padding\n");
|
||||
return RSA_Overflow;
|
||||
}
|
||||
if((padMarker == RSA_PKCS1_PAD_ENCRYPT) && (rngCallback == NULL)) {
|
||||
rsaDebug("rsaAddPkcs1Padding: RNG required\n");
|
||||
return RSA_ParamErr;
|
||||
}
|
||||
|
||||
*cp++ = 0;
|
||||
*cp++ = padMarker;
|
||||
|
||||
/*
|
||||
* RSA_PKCS1_PAD_SIGN: pad with 0xff
|
||||
* RSA_PKCS1_PAD_ENCRYPT: pad with random nonzero data
|
||||
*/
|
||||
psLen = totalLength - plainTextLen - 3;
|
||||
if(padMarker == RSA_PKCS1_PAD_ENCRYPT) {
|
||||
/* Fill cp with psLen random nonzero bytes. */
|
||||
rrtn = nonZeroRandom(rngCallback, cp, psLen);
|
||||
if (rrtn) {
|
||||
rsaDebug1("rsaAddPkcs1Padding: nonZeroRandom returned: %s\n",
|
||||
rsaStatusStr(rrtn));
|
||||
return rrtn;
|
||||
}
|
||||
|
||||
cp += psLen;
|
||||
} else {
|
||||
for(dex=0; dex<psLen; dex++) {
|
||||
*cp++ = 0xff;
|
||||
}
|
||||
}
|
||||
*cp++ = 0;
|
||||
Memcpy(cp, plainText, plainTextLen);
|
||||
RSAASSERT((cp + plainTextLen) == (giantBytes + totalLength));
|
||||
|
||||
grtn = deserializeGiant(result, giantBytes, totalLength);
|
||||
if(grtn) {
|
||||
rrtn = giantStatusToRSA(grtn);
|
||||
rsaDebug1("rsaAddPkcs1Padding: deserializeGiant returned %s\n",
|
||||
rsaStatusStr(rrtn));
|
||||
}
|
||||
return rrtn;
|
||||
}
|
||||
|
||||
#endif /* RSA_SIGN_ENABLE || RSA_ENCRYPT_ENABLE */
|
||||
|
||||
#if RSA_DECRYPT_ENABLE
|
||||
/*
|
||||
* Given decrypted plaintext in the form of a giant, which should
|
||||
* be the same size as n, verify proper PKCS1 padding and copy
|
||||
* resulting plaintext and length into caller-supplied buffer.
|
||||
* ON entry, *plainTextLen indicates the size of the available
|
||||
* plaintext buffer. ON return, *plainTextLen indicates the
|
||||
* number of valid plaintext recovered.
|
||||
*
|
||||
* FIXME don't need padMarker any more...
|
||||
*/
|
||||
RSAStatus rsaCheckPkcs1Padding(
|
||||
giant decryptResult,
|
||||
unsigned char padMarker, /* RSA_PKCS1_PAD_{SIGN,ENCRYPT} */
|
||||
unsigned char *plainText, /* data RETURNED here */
|
||||
gi_uint16 *plainTextLen) /* IN/OUT */
|
||||
{
|
||||
unsigned char giantBytes[MAX_PRIME_SIZE_BYTES];
|
||||
gi_uint16 giantBytesLen = MAX_PRIME_SIZE_BYTES;
|
||||
unsigned char *cp = giantBytes;
|
||||
GIReturn grtn;
|
||||
RSAStatus rrtn = RSA_Success;
|
||||
RSAStatus formatRtn;
|
||||
unsigned char *giantEnd;
|
||||
gi_uint16 validData;
|
||||
unsigned dex;
|
||||
|
||||
if(padMarker == RSA_PKCS1_PAD_SIGN) {
|
||||
formatRtn = RSA_BadSigFormat;
|
||||
}
|
||||
else {
|
||||
formatRtn = RSA_BadDataFormat;
|
||||
}
|
||||
if((plainText == NULL) || (decryptResult == NULL)) {
|
||||
return RSA_InternalError;
|
||||
}
|
||||
if(*plainTextLen < (MAX_PRIME_SIZE_BYTES - PKCS1_MIN_PAD_LEN)) {
|
||||
return RSA_Overflow;
|
||||
}
|
||||
grtn = serializeGiant(decryptResult, giantBytes, &giantBytesLen);
|
||||
if(grtn) {
|
||||
rrtn = giantStatusToRSA(grtn);
|
||||
rsaDebug1("rsaCheckPkcs1Padding: serializeGiant returned %s\n",
|
||||
rsaStatusStr(rrtn));
|
||||
return rrtn;
|
||||
}
|
||||
|
||||
/*
|
||||
* Leading zeroes are optional:
|
||||
*
|
||||
* 1. If the key's modulus size is not aligned to a giantDigit and the m.s.
|
||||
* byte of decryptResult - which was set to zero when the padding was
|
||||
* created - is the only byte in the m.s. giantDigit, OR giantDigit is
|
||||
* one byte, then the leading zero will not appear in the serialized
|
||||
* giantBytes.
|
||||
* 2. If the key's modulus size is not aligned to a giantDigit, and the
|
||||
* m.s. byte of decryptResult is neither the l.s. or the m.s. byte
|
||||
* of the m.s. giantDigit, then we'll see extra zeroes at the m.s.
|
||||
* end of the serialized giantBytes.
|
||||
*/
|
||||
for(dex=0; dex<GIANT_BYTES_PER_DIGIT-1; dex++) {
|
||||
if(*cp != 0) {
|
||||
break;
|
||||
}
|
||||
cp++;
|
||||
}
|
||||
if(*cp++ != padMarker) {
|
||||
rsaDebug("rsaCheckPkcs1Padding: bad padMarker\n");
|
||||
rrtn = formatRtn;
|
||||
goto errOut;
|
||||
}
|
||||
|
||||
/*
|
||||
* RSA_PKCS1_PAD_SIGN: pad with 0xff
|
||||
* RSA_PKCS1_PAD_ENCRYPT: pad with random nonzero data
|
||||
*/
|
||||
|
||||
/* mark end of valid decrypted data */
|
||||
giantEnd = giantBytes + giantBytesLen;
|
||||
do {
|
||||
unsigned char b = *cp++;
|
||||
if(b == 0) {
|
||||
/* normal termination */
|
||||
break;
|
||||
}
|
||||
if(padMarker == RSA_PKCS1_PAD_SIGN) {
|
||||
/* verify in this case else skip */
|
||||
if(b != 0xff) {
|
||||
rsaDebug("rsaCheckPkcs1Padding: SIGN pad\n");
|
||||
rrtn = formatRtn;
|
||||
goto errOut;
|
||||
}
|
||||
}
|
||||
} while (cp < giantEnd);
|
||||
|
||||
validData = giantEnd - cp;
|
||||
*plainTextLen = validData;
|
||||
if(validData != 0) {
|
||||
Memcpy(plainText, cp, validData);
|
||||
}
|
||||
errOut:
|
||||
Bzero(giantBytes, MAX_PRIME_SIZE_BYTES);
|
||||
return rrtn;
|
||||
|
||||
}
|
||||
#endif /* RSA_DECRYPT_ENABLE */
|
||||
|
||||
#endif /* RSA_PADDING_PKCS1_ENABLE */
|
||||
|
||||
#if RSA_PADDING_PKCS1_ENABLE && RSA_VERIFY_ENABLE
|
||||
|
||||
/*
|
||||
* Specialized PKCS1 padding check for signature verify operation.
|
||||
* We don't deserialize the decrypted giant; we check for padding
|
||||
* in place (in the decrypted giant's n[]), AND we do a byte-for-
|
||||
* byte compare of the expected decrypted value against memory
|
||||
* passed in to us. This saves two stack-allocated byte arrays,
|
||||
* each of MAX_PRIME_SIZE_BYTES - one here, and one in RSA_SigVerify().
|
||||
*
|
||||
* Returns:
|
||||
* -- RSA_Success, padding good and result compares OK
|
||||
* -- RSA_VerifyFail, padding good but data miscompare
|
||||
* -- RSA_BadSigFormat, bad padding
|
||||
* -- RSA_Overflow, expectPlainText too big for this key with PKCS1 padding
|
||||
* -- else usual gross errors
|
||||
*/
|
||||
RSAStatus rsaCheckPkcs1PaddingForSigVfy(
|
||||
giant decryptResult,
|
||||
const unsigned char *expectPlainText,
|
||||
gi_uint16 expectPlainTextLen)
|
||||
{
|
||||
unsigned dex;
|
||||
giantDigit *digitPtr;
|
||||
gi_uint8 byteDex;
|
||||
gi_uint8 giantByte;
|
||||
gi_size bytesLeft;
|
||||
gi_size numFFs = 0;
|
||||
|
||||
if((expectPlainText == NULL) || (decryptResult == NULL)) {
|
||||
return RSA_InternalError;
|
||||
}
|
||||
if(expectPlainTextLen > (MAX_PRIME_SIZE_BYTES - PKCS1_MIN_PAD_LEN)) {
|
||||
return RSA_Overflow;
|
||||
}
|
||||
GI_CHECK_SP("rsaCheckPkcs1PaddingForSigVfy");
|
||||
|
||||
/*
|
||||
* Prepare for scanning thru giant data, starting at the m.s. byte of the
|
||||
* m.s. digit.
|
||||
*/
|
||||
digitPtr = &decryptResult->n[decryptResult->sign - 1];
|
||||
byteDex = GIANT_BYTES_PER_DIGIT - 1;
|
||||
|
||||
/*
|
||||
* Padding of the pre-encrypted data is like so:
|
||||
*
|
||||
* one byte zero
|
||||
* one byte pad marker (RSA_PKCS1_PAD_SIGN)
|
||||
* 8 bytes of 0xff
|
||||
* one byte of zero
|
||||
* then the to-be-encrypted data
|
||||
*
|
||||
* Leading zeroes are optional:
|
||||
*
|
||||
* 1. If:
|
||||
* -- The key's modulus size is not aligned to a giantDigit, AND
|
||||
* -- the m.s. byte of decryptResult - which was set to zero when
|
||||
* the padding was created - is the only byte in the m.s.
|
||||
* giantDigit (i.e., num_bytes_of_decrypted_data mod
|
||||
* sizeof(giantDigit) equals one,
|
||||
* OR
|
||||
* -- sizeof(giantDigit) == 1 byte
|
||||
*
|
||||
* THEN the leading zero will not appear in decryptResult.
|
||||
*
|
||||
* 2. If:
|
||||
* -- The key's modulus size is not aligned to a giantDigit, AND
|
||||
* -- The m.s. byte of decryptResult is neither the l.s. or the
|
||||
* m.s. byte of the m.s. giantDigit,
|
||||
*
|
||||
* THEN then we'll see extra zeroes at the m.s. digit in decryptResult.
|
||||
*/
|
||||
for(;;) {
|
||||
giantByte = getGiantByte(digitPtr, byteDex);
|
||||
if(giantByte != 0) {
|
||||
break;
|
||||
}
|
||||
decrGiantPtrs(&digitPtr, &byteDex);
|
||||
if(digitPtr == decryptResult->n) {
|
||||
/*
|
||||
* rolled back to first digit, not enough for 11 bytes of
|
||||
* padding.
|
||||
* FIXME rewrite this when sizeof(giantDigit) > 11. :-)
|
||||
*/
|
||||
rsaDebug("rsaCheckPkcs1PaddingForSigVfy: no padMarker\n");
|
||||
return RSA_BadSigFormat;
|
||||
}
|
||||
}
|
||||
/* we're at the first nonzero byte */
|
||||
if(giantByte != RSA_PKCS1_PAD_SIGN) {
|
||||
rsaDebug("rsaCheckPkcs1PaddingForSigVfy: bad padMarker\n");
|
||||
return RSA_BadSigFormat;
|
||||
}
|
||||
decrGiantPtrs(&digitPtr, &byteDex);
|
||||
bytesLeft = bytesLeftInGiant(decryptResult, digitPtr, byteDex);
|
||||
if(bytesLeft < 9) {
|
||||
rsaDebug("rsaCheckPkcs1PaddingForSigVfy: no space left for padding\n");
|
||||
return RSA_BadSigFormat;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now skip over 0xff bytes and then one byte of zero.
|
||||
*/
|
||||
do {
|
||||
giantByte = getGiantByte(digitPtr, byteDex);
|
||||
decrGiantPtrs(&digitPtr, &byteDex);
|
||||
bytesLeft--;
|
||||
if(giantByte == 0xff) {
|
||||
numFFs++;
|
||||
continue;
|
||||
}
|
||||
else if(giantByte == 0) {
|
||||
if(numFFs < 8) {
|
||||
rsaDebug("rsaCheckPkcs1PaddingForSigVfy: insufficient padding\n");
|
||||
return RSA_BadSigFormat;
|
||||
}
|
||||
/* start of decrypted data */
|
||||
break;
|
||||
}
|
||||
else {
|
||||
rsaDebug("rsaCheckPkcs1PaddingForSigVfy: bad padding (not ff)\n");
|
||||
return RSA_BadSigFormat;
|
||||
}
|
||||
} while(bytesLeft != 0);
|
||||
|
||||
/* We're at the first decrypted data; compare with caller's expected data */
|
||||
if(bytesLeft != expectPlainTextLen) {
|
||||
rsaDebug("rsaCheckPkcs1PaddingForSigVfy: length mismatch\n");
|
||||
return RSA_VerifyFail;
|
||||
}
|
||||
|
||||
for(dex=0; dex<bytesLeft; dex++) {
|
||||
giantByte = getGiantByte(digitPtr, byteDex);
|
||||
decrGiantPtrs(&digitPtr, &byteDex);
|
||||
if(giantByte != expectPlainText[dex]) {
|
||||
rsaDebug("rsaCheckPkcs1PaddingForSigVfy: data miscompare\n");
|
||||
return RSA_VerifyFail;
|
||||
}
|
||||
}
|
||||
|
||||
/* TA DA */
|
||||
return RSA_Success;
|
||||
|
||||
}
|
||||
|
||||
#endif /* RSA_PADDING_PKCS1_ENABLE && RSA_VERIFY_ENABLE */
|
||||
@@ -0,0 +1,97 @@
|
||||
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
|
||||
|
||||
/*
|
||||
* rsaPadding.h - PKCS1 and OAEP padding support.
|
||||
*
|
||||
* Created Aug. 10 2005 by Doug Mitchell.
|
||||
*/
|
||||
|
||||
#ifndef _LIBGRSA_RSA_PADDING_H_
|
||||
#define _LIBGRSA_RSA_PADDING_H_
|
||||
|
||||
#include <libgRSA/libgRSA.h>
|
||||
#include <libGiants/giantIntegers.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* PKCS1 padding markers */
|
||||
#define RSA_PKCS1_PAD_SIGN 0x01
|
||||
#define RSA_PKCS1_PAD_ENCRYPT 0x02
|
||||
|
||||
/*
|
||||
* RP_None padding routines - just check length and convert between
|
||||
* byte array and giant
|
||||
*/
|
||||
RSAStatus rsaAddNoPadding(
|
||||
const unsigned char *plainText,
|
||||
gi_uint16 plainTextLen,
|
||||
giant result); /* RETURNED */
|
||||
|
||||
RSAStatus rsaCheckNoPadding(
|
||||
giant decryptResult,
|
||||
unsigned char *plainText, /* data RETURNED here */
|
||||
gi_uint16 *plainTextLen); /* IN/OUT */
|
||||
|
||||
/*
|
||||
* Specialized "no padding" check for signature verify operation.
|
||||
* We don't deserialize the decrypted giant; we do a byte-for-
|
||||
* byte compare of the expected decrypted value against memory
|
||||
* passed in to us, in-place in the decrypted giant.
|
||||
* This saves two stack-allocated byte arrays, each of
|
||||
* MAX_PRIME_SIZE_BYTES - one here, and one in RSA_SigVerify().
|
||||
*/
|
||||
RSAStatus rsaCheckNoPaddingForSigVfy(
|
||||
giant decryptResult,
|
||||
const unsigned char *expectPlainText,
|
||||
gi_uint16 expectPlainTextLen);
|
||||
|
||||
RSAStatus rsaAddPkcs1Padding(
|
||||
const unsigned char *plainText,
|
||||
gi_uint16 plainTextLen,
|
||||
gi_uint16 totalLength, /* intended total length */
|
||||
unsigned char padMarker, /* RSA_PKCS1_PAD_{SIGN,ENCRYPT} */
|
||||
RSARngCallback *rngCallback, /* required for RP_PKCS1, RP_OAEP */
|
||||
giant result);
|
||||
|
||||
/*
|
||||
* Given decrypted plaintext in the form of a giant, which should
|
||||
* be the same size as n, verify proper PKCS1 padding and copy
|
||||
* resulting plaintext and length into caller-supplied buffer.
|
||||
* On entry, *plainTextLen indicates the size of the available
|
||||
* plaintext buffer. On return, *plainTextLen indicates the
|
||||
* number of valid bytes of plaintext recovered.
|
||||
*/
|
||||
RSAStatus rsaCheckPkcs1Padding(
|
||||
giant decryptResult,
|
||||
unsigned char padMarker, /* RSA_PKCS1_PAD_{SIGN,ENCRYPT} */
|
||||
unsigned char *plainText, /* data RETURNED here */
|
||||
gi_uint16 *plainTextLen); /* IN/OUT */
|
||||
|
||||
/*
|
||||
* Specialized PKCS1 padding check for signature verify operation.
|
||||
* We don't deserialize the decrypted giant; we check for padding
|
||||
* in place (in the decrypted giant's n[]), AND we do a byte-for-
|
||||
* byte compare of the expected decrypted value against memory
|
||||
* passed in to us. This saves two stack-allocated byte arrays,
|
||||
* each of MAX_PRIME_SIZE_BYTES - one here, and one in RSA_SigVerify().
|
||||
*
|
||||
* Returns:
|
||||
* -- RSA_Success, padding good and result compares OK
|
||||
* -- RSA_VerifyFail, padding good but data miscompare
|
||||
* -- RSA_BadSigFormat, bad padding
|
||||
* -- RSA_Overflow, expectPlainText too big for this key with PKCS1 padding
|
||||
* -- else usual gross errors
|
||||
*/
|
||||
RSAStatus rsaCheckPkcs1PaddingForSigVfy(
|
||||
giant decryptResult,
|
||||
const unsigned char *expectPlainText,
|
||||
gi_uint16 expectPlainTextLen);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _LIBGRSA_RSA_PADDING_H_ */
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
|
||||
|
||||
/*
|
||||
* rsaRawKey.h - Typedefs and declarations for RSA keys in raw format
|
||||
*
|
||||
* Created Nov. 29 2005 by Doug Mitchell.
|
||||
*/
|
||||
|
||||
#include <libgRSA/rsaRawKey.h>
|
||||
#include <libGiants/giantExternal.h>
|
||||
#include <libGiants/giantMod.h>
|
||||
#include <libgRSA/libgRSA_config.h>
|
||||
|
||||
#ifndef RSA_RAW_KEY_ENABLE
|
||||
#error Please define RSA_RAW_KEY_ENABLE.
|
||||
#endif
|
||||
|
||||
#if RSA_RAW_KEY_ENABLE
|
||||
#if RSA_PUB_KEY_ENABLE || RSA_PRIV_KEY_ENABLE
|
||||
|
||||
/* init an lgiant, fill it with incoming bytes */
|
||||
static RSAStatus rsaSetGiant(
|
||||
lgiant *g,
|
||||
unsigned char *c,
|
||||
gi_uint16 cLen)
|
||||
{
|
||||
localGiantAlloc(g);
|
||||
if(deserializeGiant(&g->g, c, cLen)) {
|
||||
return RSA_BadKeyData;
|
||||
}
|
||||
return RSA_Success;
|
||||
}
|
||||
|
||||
#endif /* RSA_PUB_KEY_ENABLE || RSA_PRIV_KEY_ENABLE */
|
||||
|
||||
#if RSA_PUB_KEY_ENABLE
|
||||
|
||||
/* raw (n, e) in API form --> public RSAGiantKey */
|
||||
RSAStatus rsaInitPubGKey(
|
||||
const RSAPubKey *apiKey,
|
||||
RSAPubGiantKey *pubKey)
|
||||
{
|
||||
if((apiKey == NULL) || (pubKey == NULL)) {
|
||||
return RSA_ParamErr;
|
||||
}
|
||||
if((apiKey->e == NULL) || (apiKey->n == NULL)) {
|
||||
return RSA_IncompleteKey;
|
||||
}
|
||||
if(rsaSetGiant(&pubKey->n, apiKey->n, apiKey->nLen)) {
|
||||
return RSA_BadKeyData;
|
||||
}
|
||||
if(rsaSetGiant(&pubKey->e, apiKey->e, apiKey->eLen)) {
|
||||
return RSA_BadKeyData;
|
||||
}
|
||||
|
||||
localGiantAlloc(&pubKey->recip);
|
||||
if(apiKey->recip) {
|
||||
/* caller provided reciprocal */
|
||||
if(deserializeGiant(&pubKey->recip.g, apiKey->recip, apiKey->recipLen)) {
|
||||
return RSA_BadKeyData;
|
||||
}
|
||||
}
|
||||
/* else make_recip called lazily when the key is actually used */
|
||||
return RSA_Success;
|
||||
}
|
||||
|
||||
#endif /* RSA_PUB_KEY_ENABLE */
|
||||
|
||||
#if RSA_PRIV_KEY_ENABLE
|
||||
|
||||
/* init an rsaSgiant, fill it with incoming bytes */
|
||||
static RSAStatus rsaSetSGiant(
|
||||
rsaSgiant *g,
|
||||
unsigned char *c,
|
||||
gi_uint16 cLen)
|
||||
{
|
||||
localSmallGiantAlloc(g);
|
||||
if(deserializeGiant(&g->g, c, cLen)) {
|
||||
return RSA_BadKeyData;
|
||||
}
|
||||
return RSA_Success;
|
||||
}
|
||||
|
||||
/* raw (p, q, dp, dq, qInv) --> private RSAPrivCRTGiantKey */
|
||||
RSAStatus rsaInitPrivGKey(
|
||||
const RSAPrivKey *apiKey,
|
||||
RSAPrivGiantKey *privKey)
|
||||
{
|
||||
if((apiKey == NULL) || (privKey == NULL)) {
|
||||
return RSA_ParamErr;
|
||||
}
|
||||
if((apiKey->p == NULL) || (apiKey->q == NULL) || (apiKey->dp == NULL) ||
|
||||
(apiKey->dq == NULL) || (apiKey->qInv == NULL)) {
|
||||
return RSA_ParamErr;
|
||||
}
|
||||
if(rsaSetSGiant(&privKey->p, apiKey->p, apiKey->pLen)) {
|
||||
return RSA_BadKeyData;
|
||||
}
|
||||
if(rsaSetSGiant(&privKey->q, apiKey->q, apiKey->qLen)) {
|
||||
return RSA_BadKeyData;
|
||||
}
|
||||
if(rsaSetSGiant(&privKey->dp, apiKey->dp, apiKey->dpLen)) {
|
||||
return RSA_BadKeyData;
|
||||
}
|
||||
if(rsaSetSGiant(&privKey->dq, apiKey->dq, apiKey->dqLen)) {
|
||||
return RSA_BadKeyData;
|
||||
}
|
||||
if(rsaSetSGiant(&privKey->qInv, apiKey->qInv, apiKey->qInvLen)) {
|
||||
return RSA_BadKeyData;
|
||||
}
|
||||
|
||||
/* pRecip, qRecip evaluated lazily */
|
||||
localSmallGiantAlloc(&privKey->pRecip);
|
||||
localSmallGiantAlloc(&privKey->qRecip);
|
||||
|
||||
return RSA_Success;
|
||||
}
|
||||
|
||||
#endif /* RSA_PRIV_KEY_ENABLE */
|
||||
#endif /* RSA_RAW_KEY_ENABLE */
|
||||
@@ -0,0 +1,72 @@
|
||||
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
|
||||
|
||||
/*
|
||||
* rsaRawKey.h - Typedefs and declarations for RSA keys in raw format
|
||||
*
|
||||
* Created Nov. 29 2005 by Doug Mitchell.
|
||||
*/
|
||||
|
||||
#ifndef _LIBGRSA_RSA_RAW_KEY_H_
|
||||
#define _LIBGRSA_RSA_RAW_KEY_H_
|
||||
|
||||
#include <libgRSA/libgRSA.h>
|
||||
#include <libgRSA/rsaGiantKey.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Generic forms of RSA keys, public and private forms.
|
||||
* All fields are in raw, unformatted binary format, as a byte pointer
|
||||
* and a length, with the most significant byte first.
|
||||
*
|
||||
* The recip field in RSAPubKey is optional; it's the reciprocal of
|
||||
* the modulus n. Providing this field is an optimization; if it's not
|
||||
* provided, it will be calculated on the fly at some runtime cost. The
|
||||
* recip field is not sensitive; it can be distributed and stored with
|
||||
* no more security concern than the modulus itself. Providing the recip
|
||||
* field yields approximately 28% speedup on public key operations.
|
||||
*
|
||||
* See libgRSAUtils/rsaKeyGen.[ch] or Tools/rsaKeyTool for info
|
||||
* on obtaining the reciprocal.
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned char *n; /* modulus */
|
||||
gi_uint16 nLen;
|
||||
unsigned char *recip; /* reciprocal of modulus */
|
||||
gi_uint16 recipLen;
|
||||
unsigned char *e; /* public exponent */
|
||||
gi_uint16 eLen;
|
||||
} RSAPubKey;
|
||||
|
||||
/* Private key, CRT form */
|
||||
typedef struct {
|
||||
unsigned char *p;
|
||||
gi_uint16 pLen;
|
||||
unsigned char *q;
|
||||
gi_uint16 qLen;
|
||||
unsigned char *dp;
|
||||
gi_uint16 dpLen;
|
||||
unsigned char *dq;
|
||||
gi_uint16 dqLen;
|
||||
unsigned char *qInv;
|
||||
gi_uint16 qInvLen;
|
||||
} RSAPrivKey;
|
||||
|
||||
/* raw (n, e) --> public RSAPubGiantKey */
|
||||
RSAStatus rsaInitPubGKey(
|
||||
const RSAPubKey *apiKey,
|
||||
RSAPubGiantKey *pubKey);
|
||||
|
||||
/* raw (p, q, dp, dq, qInv) --> private RSAPrivGiantKey */
|
||||
RSAStatus rsaInitPrivGKey(
|
||||
const RSAPrivKey *apiKey,
|
||||
RSAPrivGiantKey *privKey);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _LIBGRSA_RSA_CORE_H_ */
|
||||
@@ -0,0 +1,66 @@
|
||||
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
|
||||
|
||||
/*
|
||||
* rsaTypes.h - typedefs for libgRSA
|
||||
*
|
||||
* Created Nov. 30 2005 by Doug Mitchell.
|
||||
*/
|
||||
|
||||
#ifndef _LIBRSA_RSA_TYPES_H_
|
||||
#define _LIBRSA_RSA_TYPES_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <libGiants/giantTypes.h>
|
||||
|
||||
/*
|
||||
* Error returns from this library.
|
||||
*/
|
||||
typedef enum {
|
||||
RSA_Success = 0,
|
||||
RSA_BadKeyData = RSA_RETURN_BASE, /* bad raw key data */
|
||||
RSA_ParamErr, /* parameter error */
|
||||
RSA_IncompleteKey, /* one or more RSAKey fields missing */
|
||||
RSA_VerifyFail, /* signature verification failed */
|
||||
RSA_BadSigFormat, /* improperly formatted signature */
|
||||
RSA_BadDataFormat, /* improperly formatted ciphertext */
|
||||
RSA_BadKeyFormat, /* improperly formatted public key */
|
||||
RSA_InternalError, /* internal error */
|
||||
RSA_Overflow, /* insufficent buffer provided */
|
||||
RSA_Unimplemented, /* unimplemented in this configuration */
|
||||
RSA_IllegalKeySize, /* Unsupported key size */
|
||||
RSA_OtherError
|
||||
} RSAStatus;
|
||||
|
||||
/*
|
||||
* Padding styles
|
||||
*/
|
||||
typedef enum {
|
||||
RP_None = 0, /* no padding */
|
||||
RP_PKCS1, /* PKCS1, for signing and encrypting */
|
||||
RP_OAEP /* OAEP, for encrypting only */
|
||||
} RSAPadding;
|
||||
|
||||
/*
|
||||
* Random number callback function. The caller of RSA_Encrypt or
|
||||
* RSA_GenKeyPair supplies pseudorandom data for OAEP or PKCS1 padding
|
||||
* generation or for key generation, via this callback.
|
||||
*
|
||||
* The destination of the random data is *randBuf, which is memory owned
|
||||
* and maintained by the caller of this function.
|
||||
*
|
||||
* This function should return nonzero if it failed to obtain the number of
|
||||
* random bytes requested.
|
||||
*/
|
||||
typedef int (RSARngCallback)(
|
||||
gi_uint8 *randBuf, /* random data goes here */
|
||||
gi_uint16 randSize); /* byte count */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _LIBRSA_RSA_TYPES_H_ */
|
||||
|
||||
Reference in new issue
Block a user