first and last commit

This commit is contained in:
Chris Nutter committed 2023-07-08 13:03:17 -07:00
commit 1bf4efd552
2612 files changed
+636500

No files matched your search

+383
View File
@@ -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 */
+187
View File
@@ -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_ */
+440
View File
@@ -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 */
+120
View File
@@ -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_ */
+48
View File
@@ -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_ */
+86
View File
@@ -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 */
+56
View File
@@ -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_ */
+38
View File
@@ -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));
}
+78
View File
@@ -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_ */
+532
View File
@@ -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 */
+97
View File
@@ -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_ */
+120
View File
@@ -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 */
+72
View File
@@ -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_ */
+66
View File
@@ -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_ */