📄 import.c
字号:
/*____________________________________________________________________________
Copyright (C) 2002 PGP Corporation
All rights reserved.
$Id: import.c,v 1.7 2002/08/06 20:11:08 dallen Exp $
____________________________________________________________________________*/
/*
* import.c - routines for importing a PKCS-12
* Author: Michael_Elkins@NAI.com
*/
#include "pbe12.h"
#include "pgpSymmetricCipherPriv.h" /* For RC2 ciphers */
#define kPGPMACSize 20 /* pkcs#12 requires 160-bit MAC keys */
/* compute HMAC-SHA */
/* If it doesn't verify, assume it's because of a bad passphrase */
static PGPError
pkcs12VerifyMAC (
PKICONTEXT *context,
PKIPFX *pfx,
const unsigned char *password,
size_t passwordLen)
{
unsigned char *mackey=NULL;
unsigned char mac[kPGPMACSize];
size_t mackeylen = kPGPMACSize;
int asnerror=0;
PKIOCTET_STRING *oct=NULL;
PGPError err=kPGPError_LazyProgrammer;
PGPHMACContextRef hmacref;
if(!context||!pfx)
return err;
if(!pfx->macData)
return kPGPError_NoErr;/*nothing to do*/
#ifdef LOUD
pbe12DumpBytes("HMAC salt:", pfx->macData->macSalt.val,pfx->macData->macSalt.len);
#endif
pbe12GenerateRandomBits(context->customValue,
kPGPHashAlgorithm_SHA,
kPGPPBEIDMACKey,
pfx->macData->macIterationCount ? PKIGetIntVal(context,pfx->macData->macIterationCount,&asnerror) : 1,
pfx->macData->macSalt.val,
pfx->macData->macSalt.len,
password,
passwordLen,
mackeylen,
&mackey);
PKIUnpackOCTET_STRING(context,&oct,pfx->authSafes.content->val,pfx->authSafes.content->len,&asnerror);
if(asnerror)
goto error;
err = PGPNewHMACContext(context->customValue,
kPGPHashAlgorithm_SHA,
mackey,
mackeylen,
&hmacref);
if (IsPGPError(err))
goto error;
err = PGPContinueHMAC(hmacref,oct->val,oct->len);
if (IsPGPError(err))
goto error;
err = PGPFinalizeHMAC(hmacref,mac);
if (IsPGPError(err))
goto error;
err = PGPFreeHMACContext(hmacref);
if (IsPGPError(err))
goto error;
if (pfx->macData->mac.digest.len != kPGPMACSize ||
memcmp(mac,pfx->macData->mac.digest.val,kPGPMACSize))
{
err = kPGPError_BadPassphrase;
goto error;
}
err=kPGPError_NoErr;
error:
if (mackey)
PKIFree(context->memMgr,mackey);
if (oct)
PKIFreeOCTET_STRING(context,oct);
return err;
}
static PGPPBEAlgorithm
pkcs12PBEAlgorithm (const unsigned char *oid, size_t oidsize)
{
if (oidsize == PKIpbeWithSHA1And3_KeyTripleDES_CBC_OID_LEN &&
!memcmp (oid,PKIpbeWithSHA1And3_KeyTripleDES_CBC_OID,oidsize))
return kPGPPBEAlgorithm_SHA3DES;
if (oidsize == PKIpbeWithSHA1And2_KeyTripleDES_CBC_OID_LEN &&
!memcmp (oid,PKIpbeWithSHA1And2_KeyTripleDES_CBC_OID,oidsize))
return kPGPPBEAlgorithm_SHADESEDE2;
if (oidsize == PKIpbeWithSHA1And128BitRC4_OID_LEN &&
!memcmp (oid, PKIpbeWithSHA1And128BitRC4_OID, oidsize))
return kPGPPBEAlgorithm_SHARC4_128;
if (oidsize == PKIpbeWithSHA1And40BitRC4_OID_LEN &&
!memcmp (oid, PKIpbeWithSHA1And40BitRC4_OID, oidsize))
return kPGPPBEAlgorithm_SHARC4_40;
if (oidsize == PKIpbeWithSHA1And128BitRC2_CBC_OID_LEN &&
!memcmp (oid, PKIpbeWithSHA1And128BitRC2_CBC_OID, oidsize))
return kPGPPBEAlgorithm_SHARC2_128;
if (oidsize == PKIpbeWithSHA1And40BitRC2_CBC_OID_LEN &&
!memcmp (oid, PKIpbeWithSHA1And40BitRC2_CBC_OID, oidsize))
return kPGPPBEAlgorithm_SHARC2_40;
return kPGPPBEAlgorithm_Unknown;
}
typedef enum {
kPGPBagType_Unknown,
kPGPBagType_KeyBag,
kPGPBagType_PKCS8ShroudedKeyBag,
kPGPBagType_CertBag,
kPGPBagType_CRLBag,
kPGPBagType_SecretBag,
kPGPBagType_SafeContentsBag
} PGPBagType;
static PGPBagType
pkcs12BagType (
const unsigned char *oid,
size_t oidsize)
{
if(oidsize==PKIkeyBag_OID_LEN && !memcmp(PKIkeyBag_OID,oid,oidsize))
return kPGPBagType_KeyBag;
if(oidsize==PKIpkcs_8ShroudedKeyBag_OID_LEN && !memcmp(PKIpkcs_8ShroudedKeyBag_OID,oid,oidsize))
return kPGPBagType_PKCS8ShroudedKeyBag;
if(oidsize==PKIcertBag_OID_LEN && !memcmp(PKIcertBag_OID,oid,oidsize))
return kPGPBagType_CertBag;
if(oidsize==PKIcrlBag_OID_LEN && !memcmp(PKIcrlBag_OID,oid,oidsize))
return kPGPBagType_CRLBag;
if(oidsize==PKIsecretBag_OID_LEN && !memcmp(PKIsecretBag_OID,oid,oidsize))
return kPGPBagType_SecretBag;
if(oidsize==PKIsafeContentsBag_OID_LEN && !memcmp(PKIsafeContentsBag_OID,oid,oidsize))
return kPGPBagType_SafeContentsBag;
return kPGPBagType_Unknown;
}
#if 0
static unsigned char pbe12OddParity[256] = {
1, 1, 2, 2, 4, 4, 7, 7, 8, 8, 11, 11, 13, 13, 14, 14,
16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28, 31, 31,
32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44, 44, 47, 47,
49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59, 61, 61, 62, 62,
64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74, 74, 76, 76, 79, 79,
81, 81, 82, 82, 84, 84, 87, 87, 88, 88, 91, 91, 93, 93, 94, 94,
97, 97, 98, 98, 100, 100, 103, 103, 104, 104, 107, 107, 109, 109, 110, 110,
112, 112, 115, 115, 117, 117, 118, 118, 121, 121, 122, 122, 124, 124, 127, 127,
128, 128, 131, 131, 133, 133, 134, 134, 137, 137, 138, 138, 140, 140, 143, 143,
145, 145, 146, 146, 148, 148, 151, 151, 152, 152, 155, 155, 157, 157, 158, 158,
161, 161, 162, 162, 164, 164, 167, 167, 168, 168, 171, 171, 173, 173, 174, 174,
176, 176, 179, 179, 181, 181, 182, 182, 185, 185, 186, 186, 188, 188, 191, 191,
193, 193, 194, 194, 196, 196, 199, 199, 200, 200, 203, 203, 205, 205, 206, 206,
208, 208, 211, 211, 213, 213, 214, 214, 217, 217, 218, 218, 220, 220, 223, 223,
224, 224, 227, 227, 229, 229, 230, 230, 233, 233, 234, 234, 236, 236, 239, 239,
241, 241, 242, 242, 244, 244, 247, 247, 248, 248, 251, 251, 253, 253, 254, 254
};
static void pbe12SetOddParity (PGPByte *b)
{
int i;
for (i = 0; i < 24; i++)
b[i] = pbe12OddParity[b[i]];
}
#endif
/*
* Do a PKCS-12 style decryption of a buffer into a dynamically allocated
* buffer
*/
static PGPError
pkcs12Decrypt(
PGPContextRef context, /* [IN] */
const PGPByte *pass, /* [IN] */
PGPSize passsize, /* [IN] */
const PGPByte *encdata, /* [IN] data to decrypt */
PGPSize encdatasize, /* [IN] size of data to decrypt
(bytes) */
PKIEncryptionAlgorithmIdentifier *alginfo, /* [IN] alg info */
PKICONTEXT *pki, /* [IN] asn.1 compiler
context */
PGPByte **outbuf, /* [OUT] outptu buffer */
PGPSize *outbufsize) /* [OUT] output size */
{
PKIpkcs_12PbeParams *param = NULL;
int asnerr = 0, itercount;
PGPPBEAlgorithm alg;
PGPError err;
PGPByte *symkey = NULL, *iv = NULL, pad;
PGPSize keysize, blocksize, i;
PGPHashAlgorithm hashalg;
PGPCipherAlgorithm encalg;
PGPCBCContextRef cbcref = NULL;
PGPSymmetricCipherContextRef symref = NULL;
PGPMemoryMgrRef mem = PGPPeekContextMemoryMgr (context);
/* determine what algorithm was used to encrypt */
alg = pkcs12PBEAlgorithm (alginfo->algorithm.val,alginfo->algorithm.len);
switch (alg)
{
case kPGPPBEAlgorithm_SHA3DES:
hashalg = kPGPHashAlgorithm_SHA;
encalg = kPGPCipherAlgorithm_3DES;
keysize = 24;
break;
case kPGPPBEAlgorithm_SHARC2_40:
hashalg = kPGPHashAlgorithm_SHA;
encalg = (PGPCipherAlgorithm)kPGPCipherAlgorithm_RC2_40;
keysize = 40/8;
break;
case kPGPPBEAlgorithm_SHARC2_128:
hashalg = kPGPHashAlgorithm_SHA;
encalg = (PGPCipherAlgorithm)kPGPCipherAlgorithm_RC2_128;
keysize = 128/8;
break;
default:
err = kPGPError_BadHashNumber;
goto error;
}
/* set up encryption context */
err = PGPNewSymmetricCipherContext (context, encalg, &symref);
if (IsPGPError (err))
goto error;
/* determine key and block sizes */
err = PGPGetSymmetricCipherSizes (symref, &keysize, &blocksize);
if (IsPGPError (err))
goto error;
/* decode pbe parameters */
/* this assumes that we aren't using any of the PKCS-5 modes */
PKIUnpackpkcs_12PbeParams (pki, ¶m, alginfo->parameters->val,
alginfo->parameters->len, &asnerr);
if (asnerr)
{
err = kPGPError_LazyProgrammer;
goto error;
}
itercount = PKIGetIntVal (pki, ¶m->iterationCount, &asnerr);
if (asnerr)
{
err = kPGPError_LazyProgrammer;
goto error;
}
/* generate the symmetric cipher key */
err = pbe12GenerateRandomBits (context,
hashalg,
kPGPPBEIDEncryptKey,
itercount,
param->salt.val,
param->salt.len,
pass,
passsize,
keysize,
&symkey);
if (IsPGPError (err))
goto error;
/* generate the IV */
err = pbe12GenerateRandomBits (context,
hashalg,
kPGPPBEIDIV,
itercount,
param->salt.val,
param->salt.len,
pass,
passsize,
blocksize,
&iv);
if (IsPGPError (err))
goto error;
err = PGPNewCBCContext (symref, &cbcref);
if (IsPGPError (err))
goto error;
symref = NULL; /* dont free this, PGPFreeCBCContext does it */
err = PGPInitCBC (cbcref, symkey, iv);
if (IsPGPError (err))
goto error;
*outbufsize = encdatasize;
*outbuf = PGPNewData (mem, *outbufsize, 0);
err = PGPCBCDecrypt (cbcref, encdata, encdatasize, *outbuf);
if (IsPGPError (err))
goto error;
/* remove padding */
pad = (*outbuf)[*outbufsize - 1];
if (pad < 1 || pad > blocksize)
{
/* invalid pad size, decryption failed */
err = kPGPError_LazyProgrammer;
goto error;
}
*outbufsize -= pad;
/* ensure that we have a valid pad */
for (i = 0; i < pad; i++)
if ((*outbuf)[*outbufsize + i] != pad)
{
/* invalid pad, decryption failed */
err = kPGPError_LazyProgrammer;
goto error;
}
err = kPGPError_NoErr;
error:
if (symref)
err = PGPFreeSymmetricCipherContext (symref);
if (cbcref)
err = PGPFreeCBCContext (cbcref);
if (param)
PKIFreepkcs_12PbeParams (pki, param);
if (symkey)
PGPFreeData (symkey);
if (iv)
PGPFreeData (iv);
return err;
}
/* processes a PKCS #8 EncryptedPrivateKeyInfo ASN.1 blob */
static PGPError
pkcs8Decrypt (
PGPContextRef context, /* [IN] */
const PGPByte *pass, /* [IN] */
PGPSize passsize, /* [IN] */
const PGPByte *encdata, /* [IN] data to decrypt */
PGPSize encdatasize, /* [IN] size of data to decrypt
(bytes) */
PKICONTEXT *pki, /* [IN] asn.1 compiler
context */
PGPByte **privkey, /* [OUT] PrivateKeyInfo ASN.1 */
PGPSize *privkeysize) /* [OUT] asn.1 binary size */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -