2011-11-04 22:28:50 +08:00
|
|
|
#include "system.h"
|
|
|
|
|
|
|
|
#include <pthread.h>
|
|
|
|
#include <nss.h>
|
|
|
|
#include <sechash.h>
|
|
|
|
#include <keyhi.h>
|
|
|
|
#include <cryptohi.h>
|
2012-11-29 16:43:24 +08:00
|
|
|
#include <blapit.h>
|
2011-11-04 22:28:50 +08:00
|
|
|
|
|
|
|
#include <rpm/rpmlog.h>
|
|
|
|
#include "rpmio/digest.h"
|
|
|
|
#include "debug.h"
|
|
|
|
|
|
|
|
|
|
|
|
static int _crypto_initialized = 0;
|
|
|
|
static int _new_process = 1;
|
|
|
|
|
2012-10-31 15:43:38 +08:00
|
|
|
#if HAVE_NSS_INITCONTEXT
|
|
|
|
static NSSInitContext * _nss_ctx = NULL;
|
|
|
|
#endif
|
|
|
|
|
2011-11-04 22:28:50 +08:00
|
|
|
/**
|
|
|
|
* MD5/SHA1 digest private data.
|
|
|
|
*/
|
|
|
|
struct DIGEST_CTX_s {
|
|
|
|
rpmDigestFlags flags; /*!< Bit(s) to control digest operation. */
|
|
|
|
HASHContext *hashctx; /*!< Internal NSS hash context. */
|
|
|
|
int algo; /*!< Used hash algorithm */
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Only flag for re-initialization here, in the common case the child
|
|
|
|
* exec()'s something else shutting down NSS here would be waste of time.
|
|
|
|
*/
|
|
|
|
static void at_forkchild(void)
|
|
|
|
{
|
|
|
|
_new_process = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int rpmInitCrypto(void)
|
|
|
|
{
|
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
/* Lazy NSS shutdown for re-initialization after fork() */
|
|
|
|
if (_new_process && _crypto_initialized) {
|
|
|
|
rpmFreeCrypto();
|
|
|
|
}
|
|
|
|
|
2012-10-31 15:43:38 +08:00
|
|
|
/*
|
|
|
|
* Initialize NSS if not already done.
|
|
|
|
* NSS prior to 3.12.5 only supports a global context which can cause
|
|
|
|
* trouble when an API user wants to use NSS for their own purposes, use
|
|
|
|
* a private context if possible.
|
|
|
|
*/
|
2011-11-04 22:28:50 +08:00
|
|
|
if (!_crypto_initialized) {
|
2012-10-31 15:43:38 +08:00
|
|
|
#if HAVE_NSS_INITCONTEXT
|
|
|
|
PRUint32 flags = (NSS_INIT_READONLY|NSS_INIT_NOCERTDB|
|
|
|
|
NSS_INIT_NOMODDB|NSS_INIT_FORCEOPEN|
|
|
|
|
NSS_INIT_NOROOTINIT|NSS_INIT_OPTIMIZESPACE);
|
|
|
|
_nss_ctx = NSS_InitContext(NULL, NULL, NULL, NULL, NULL, flags);
|
|
|
|
if (_nss_ctx == NULL) {
|
|
|
|
#else
|
2011-11-04 22:28:50 +08:00
|
|
|
if (NSS_NoDB_Init(NULL) != SECSuccess) {
|
2012-10-31 15:43:38 +08:00
|
|
|
#endif
|
2013-02-12 11:14:34 +08:00
|
|
|
rpmlog(RPMLOG_ERR, _("Failed to initialize NSS library\n"));
|
2011-11-04 22:28:50 +08:00
|
|
|
rc = -1;
|
|
|
|
} else {
|
|
|
|
_crypto_initialized = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Register one post-fork handler per process */
|
|
|
|
if (_new_process) {
|
|
|
|
if (pthread_atfork(NULL, NULL, at_forkchild) != 0) {
|
|
|
|
rpmlog(RPMLOG_WARNING, _("Failed to register fork handler: %m\n"));
|
|
|
|
}
|
|
|
|
_new_process = 0;
|
|
|
|
}
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
int rpmFreeCrypto(void)
|
|
|
|
{
|
|
|
|
int rc = 0;
|
|
|
|
if (_crypto_initialized) {
|
2012-10-31 15:43:38 +08:00
|
|
|
#if HAVE_NSS_INITCONTEXT
|
|
|
|
rc = (NSS_ShutdownContext(_nss_ctx) != SECSuccess);
|
|
|
|
_nss_ctx = NULL;
|
|
|
|
#else
|
2011-11-04 22:28:50 +08:00
|
|
|
rc = (NSS_Shutdown() != SECSuccess);
|
2012-10-31 15:43:38 +08:00
|
|
|
#endif
|
2011-11-04 22:28:50 +08:00
|
|
|
_crypto_initialized = 0;
|
|
|
|
}
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
DIGEST_CTX rpmDigestDup(DIGEST_CTX octx)
|
|
|
|
{
|
|
|
|
DIGEST_CTX nctx = NULL;
|
|
|
|
if (octx) {
|
|
|
|
HASHContext *hctx = HASH_Clone(octx->hashctx);
|
|
|
|
if (hctx) {
|
|
|
|
nctx = memcpy(xcalloc(1, sizeof(*nctx)), octx, sizeof(*nctx));
|
|
|
|
nctx->hashctx = hctx;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nctx;
|
|
|
|
}
|
|
|
|
|
|
|
|
RPM_GNUC_PURE
|
|
|
|
static HASH_HashType getHashType(int hashalgo)
|
|
|
|
{
|
|
|
|
switch (hashalgo) {
|
2012-11-30 18:20:05 +08:00
|
|
|
case PGPHASHALGO_MD5: return HASH_AlgMD5;
|
|
|
|
case PGPHASHALGO_MD2: return HASH_AlgMD2;
|
|
|
|
case PGPHASHALGO_SHA1: return HASH_AlgSHA1;
|
2012-11-30 18:23:42 +08:00
|
|
|
#ifdef SHA224_LENGTH
|
2012-11-30 18:20:05 +08:00
|
|
|
case PGPHASHALGO_SHA224: return HASH_AlgSHA224;
|
2012-11-30 18:23:42 +08:00
|
|
|
#endif
|
2012-11-30 18:20:05 +08:00
|
|
|
case PGPHASHALGO_SHA256: return HASH_AlgSHA256;
|
|
|
|
case PGPHASHALGO_SHA384: return HASH_AlgSHA384;
|
|
|
|
case PGPHASHALGO_SHA512: return HASH_AlgSHA512;
|
2011-11-04 22:28:50 +08:00
|
|
|
}
|
2012-11-30 18:20:05 +08:00
|
|
|
return HASH_AlgNULL;
|
2011-11-04 22:28:50 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
size_t rpmDigestLength(int hashalgo)
|
|
|
|
{
|
|
|
|
return HASH_ResultLen(getHashType(hashalgo));
|
|
|
|
}
|
|
|
|
|
|
|
|
DIGEST_CTX rpmDigestInit(int hashalgo, rpmDigestFlags flags)
|
|
|
|
{
|
|
|
|
HASH_HashType type = getHashType(hashalgo);
|
|
|
|
HASHContext *hashctx = NULL;
|
|
|
|
DIGEST_CTX ctx = NULL;
|
|
|
|
|
|
|
|
if (type == HASH_AlgNULL || rpmInitCrypto() < 0)
|
|
|
|
goto exit;
|
|
|
|
|
|
|
|
if ((hashctx = HASH_Create(type)) != NULL) {
|
|
|
|
ctx = xcalloc(1, sizeof(*ctx));
|
|
|
|
ctx->flags = flags;
|
|
|
|
ctx->algo = hashalgo;
|
|
|
|
ctx->hashctx = hashctx;
|
|
|
|
HASH_Begin(ctx->hashctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
exit:
|
|
|
|
return ctx;
|
|
|
|
}
|
|
|
|
|
|
|
|
int rpmDigestUpdate(DIGEST_CTX ctx, const void * data, size_t len)
|
|
|
|
{
|
|
|
|
size_t partlen;
|
|
|
|
const unsigned char *ptr = data;
|
|
|
|
|
|
|
|
if (ctx == NULL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
partlen = ~(unsigned int)0xFF;
|
|
|
|
while (len > 0) {
|
|
|
|
if (len < partlen) {
|
|
|
|
partlen = len;
|
|
|
|
}
|
|
|
|
HASH_Update(ctx->hashctx, ptr, partlen);
|
|
|
|
ptr += partlen;
|
|
|
|
len -= partlen;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int rpmDigestFinal(DIGEST_CTX ctx, void ** datap, size_t *lenp, int asAscii)
|
|
|
|
{
|
|
|
|
unsigned char * digest;
|
|
|
|
unsigned int digestlen;
|
|
|
|
|
|
|
|
if (ctx == NULL)
|
|
|
|
return -1;
|
|
|
|
digestlen = HASH_ResultLenContext(ctx->hashctx);
|
|
|
|
digest = xmalloc(digestlen);
|
|
|
|
|
|
|
|
/* FIX: check rc */
|
|
|
|
HASH_End(ctx->hashctx, digest, (unsigned int *) &digestlen, digestlen);
|
|
|
|
|
|
|
|
/* Return final digest. */
|
|
|
|
if (!asAscii) {
|
|
|
|
if (lenp) *lenp = digestlen;
|
|
|
|
if (datap) {
|
|
|
|
*datap = digest;
|
|
|
|
digest = NULL;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (lenp) *lenp = (2*digestlen) + 1;
|
|
|
|
if (datap) {
|
|
|
|
const uint8_t * s = (const uint8_t *) digest;
|
|
|
|
*datap = pgpHexStr(s, digestlen);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (digest) {
|
|
|
|
memset(digest, 0, digestlen); /* In case it's sensitive */
|
|
|
|
free(digest);
|
|
|
|
}
|
|
|
|
HASH_Destroy(ctx->hashctx);
|
|
|
|
memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
|
|
|
|
free(ctx);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-11-29 18:35:13 +08:00
|
|
|
RPM_GNUC_PURE
|
|
|
|
static SECOidTag getHashAlg(unsigned int hashalgo)
|
|
|
|
{
|
|
|
|
switch (hashalgo) {
|
|
|
|
case PGPHASHALGO_MD5: return SEC_OID_MD5;
|
|
|
|
case PGPHASHALGO_MD2: return SEC_OID_MD2;
|
|
|
|
case PGPHASHALGO_SHA1: return SEC_OID_SHA1;
|
2012-11-30 18:23:42 +08:00
|
|
|
#ifdef SHA224_LENGTH
|
2012-11-29 18:35:13 +08:00
|
|
|
case PGPHASHALGO_SHA224: return SEC_OID_SHA224;
|
2012-11-30 18:23:42 +08:00
|
|
|
#endif
|
2012-11-29 18:35:13 +08:00
|
|
|
case PGPHASHALGO_SHA256: return SEC_OID_SHA256;
|
|
|
|
case PGPHASHALGO_SHA384: return SEC_OID_SHA384;
|
|
|
|
case PGPHASHALGO_SHA512: return SEC_OID_SHA512;
|
|
|
|
}
|
|
|
|
return SEC_OID_UNKNOWN;
|
|
|
|
}
|
|
|
|
|
2013-08-29 00:31:47 +08:00
|
|
|
static int pgpMpiSet(unsigned int lbits, uint8_t *dest, const uint8_t * p)
|
2011-11-04 22:28:50 +08:00
|
|
|
{
|
|
|
|
unsigned int mbits = pgpMpiBits(p);
|
|
|
|
unsigned int nbits;
|
|
|
|
size_t nbytes;
|
|
|
|
uint8_t *t = dest;
|
|
|
|
unsigned int ix;
|
|
|
|
|
|
|
|
if (mbits > lbits)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
nbits = (lbits > mbits ? lbits : mbits);
|
|
|
|
nbytes = ((nbits + 7) >> 3);
|
|
|
|
ix = (nbits - mbits) >> 3;
|
|
|
|
|
|
|
|
if (ix > 0)
|
|
|
|
memset(t, '\0', ix);
|
|
|
|
memcpy(t+ix, p+2, nbytes-ix);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-08-29 00:31:47 +08:00
|
|
|
static SECItem *pgpMpiItem(PRArenaPool *arena, SECItem *item, const uint8_t *p)
|
2011-11-04 22:28:50 +08:00
|
|
|
{
|
|
|
|
size_t nbytes = pgpMpiLen(p)-2;
|
|
|
|
|
|
|
|
if (item == NULL) {
|
|
|
|
if ((item=SECITEM_AllocItem(arena, item, nbytes)) == NULL)
|
|
|
|
return item;
|
|
|
|
} else {
|
|
|
|
if (arena != NULL)
|
|
|
|
item->data = PORT_ArenaGrow(arena, item->data, item->len, nbytes);
|
|
|
|
else
|
|
|
|
item->data = PORT_Realloc(item->data, nbytes);
|
|
|
|
|
|
|
|
if (item->data == NULL) {
|
|
|
|
if (arena == NULL)
|
|
|
|
SECITEM_FreeItem(item, PR_TRUE);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(item->data, p+2, nbytes);
|
|
|
|
item->len = nbytes;
|
|
|
|
return item;
|
|
|
|
}
|
|
|
|
|
|
|
|
static SECKEYPublicKey *pgpNewPublicKey(KeyType type)
|
|
|
|
{
|
|
|
|
PRArenaPool *arena;
|
|
|
|
SECKEYPublicKey *key;
|
|
|
|
|
|
|
|
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
|
|
|
if (arena == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
key = PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey));
|
|
|
|
|
|
|
|
if (key == NULL) {
|
|
|
|
PORT_FreeArena(arena, PR_FALSE);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
key->keyType = type;
|
|
|
|
key->pkcs11ID = CK_INVALID_HANDLE;
|
|
|
|
key->pkcs11Slot = NULL;
|
|
|
|
key->arena = arena;
|
|
|
|
return key;
|
|
|
|
}
|
|
|
|
|
2012-11-29 16:43:24 +08:00
|
|
|
/* compatibility with nss < 3.14 */
|
2014-05-19 20:39:49 +08:00
|
|
|
#ifndef DSA1_SUBPRIME_LEN
|
|
|
|
#define DSA1_SUBPRIME_LEN DSA_SUBPRIME_LEN
|
2011-11-04 22:28:50 +08:00
|
|
|
#endif
|
2014-05-19 20:39:49 +08:00
|
|
|
#ifndef DSA1_SIGNATURE_LEN
|
|
|
|
#define DSA1_SIGNATURE_LEN DSA_SIGNATURE_LEN
|
|
|
|
#endif
|
|
|
|
#ifndef DSA1_Q_BITS
|
|
|
|
#define DSA1_Q_BITS DSA_Q_BITS
|
2012-11-29 17:05:04 +08:00
|
|
|
#endif
|
2011-11-04 22:28:50 +08:00
|
|
|
|
2013-08-29 00:31:47 +08:00
|
|
|
static int pgpSetSigMpiDSA(pgpDigAlg pgpsig, int num, const uint8_t *p)
|
2011-11-04 22:28:50 +08:00
|
|
|
{
|
|
|
|
SECItem *sig = pgpsig->data;
|
2014-05-19 20:39:49 +08:00
|
|
|
unsigned int qbits = DSA1_Q_BITS;
|
|
|
|
unsigned int subprlen = DSA1_SUBPRIME_LEN;
|
|
|
|
unsigned int siglen = DSA1_SIGNATURE_LEN;
|
2011-11-04 22:28:50 +08:00
|
|
|
int rc = 1; /* assume failure */
|
|
|
|
|
|
|
|
switch (num) {
|
|
|
|
case 0:
|
2014-05-19 20:39:49 +08:00
|
|
|
sig = pgpsig->data = SECITEM_AllocItem(NULL, NULL, siglen);
|
2012-12-04 20:06:42 +08:00
|
|
|
if (sig) {
|
2012-12-13 19:27:09 +08:00
|
|
|
memset(sig->data, 0, siglen);
|
2013-08-29 00:31:47 +08:00
|
|
|
rc = pgpMpiSet(qbits, sig->data, p);
|
2012-12-04 20:06:42 +08:00
|
|
|
}
|
2011-11-04 22:28:50 +08:00
|
|
|
break;
|
|
|
|
case 1:
|
2013-08-29 00:31:47 +08:00
|
|
|
if (sig && pgpMpiSet(qbits, sig->data+subprlen, p) == 0) {
|
2011-11-04 22:28:50 +08:00
|
|
|
SECItem *signew = SECITEM_AllocItem(NULL, NULL, 0);
|
2012-12-13 19:27:09 +08:00
|
|
|
if (signew == NULL)
|
|
|
|
break;
|
|
|
|
if (DSAU_EncodeDerSigWithLen(signew, sig, siglen) == SECSuccess) {
|
2011-11-04 22:28:50 +08:00
|
|
|
SECITEM_FreeItem(sig, PR_TRUE);
|
|
|
|
pgpsig->data = signew;
|
|
|
|
rc = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2013-08-29 00:31:47 +08:00
|
|
|
static int pgpSetKeyMpiDSA(pgpDigAlg pgpkey, int num, const uint8_t *p)
|
2011-11-04 22:28:50 +08:00
|
|
|
{
|
|
|
|
SECItem *mpi = NULL;
|
|
|
|
SECKEYPublicKey *key = pgpkey->data;
|
|
|
|
|
|
|
|
if (key == NULL)
|
|
|
|
key = pgpkey->data = pgpNewPublicKey(dsaKey);
|
|
|
|
|
|
|
|
if (key) {
|
|
|
|
switch (num) {
|
|
|
|
case 0:
|
2013-08-29 00:31:47 +08:00
|
|
|
mpi = pgpMpiItem(key->arena, &key->u.dsa.params.prime, p);
|
2011-11-04 22:28:50 +08:00
|
|
|
break;
|
|
|
|
case 1:
|
2013-08-29 00:31:47 +08:00
|
|
|
mpi = pgpMpiItem(key->arena, &key->u.dsa.params.subPrime, p);
|
2011-11-04 22:28:50 +08:00
|
|
|
break;
|
|
|
|
case 2:
|
2013-08-29 00:31:47 +08:00
|
|
|
mpi = pgpMpiItem(key->arena, &key->u.dsa.params.base, p);
|
2011-11-04 22:28:50 +08:00
|
|
|
break;
|
|
|
|
case 3:
|
2013-08-29 00:31:47 +08:00
|
|
|
mpi = pgpMpiItem(key->arena, &key->u.dsa.publicValue, p);
|
2011-11-04 22:28:50 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return (mpi == NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int pgpVerifySigDSA(pgpDigAlg pgpkey, pgpDigAlg pgpsig,
|
|
|
|
uint8_t *hash, size_t hashlen, int hash_algo)
|
|
|
|
{
|
|
|
|
SECItem digest = { .type = siBuffer, .data = hash, .len = hashlen };
|
2012-11-29 18:35:13 +08:00
|
|
|
SECOidTag encAlg = SEC_OID_ANSIX9_DSA_SIGNATURE;
|
|
|
|
SECOidTag hashAlg = getHashAlg(hash_algo);
|
2011-11-04 22:28:50 +08:00
|
|
|
SECStatus rc;
|
|
|
|
|
2012-11-29 18:35:13 +08:00
|
|
|
if (hashAlg == SEC_OID_UNKNOWN)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
rc = VFY_VerifyDigestDirect(&digest, pgpkey->data, pgpsig->data,
|
|
|
|
encAlg, hashAlg, NULL);
|
2011-11-04 22:28:50 +08:00
|
|
|
|
|
|
|
return (rc != SECSuccess);
|
|
|
|
}
|
|
|
|
|
2013-08-29 00:31:47 +08:00
|
|
|
static int pgpSetSigMpiRSA(pgpDigAlg pgpsig, int num, const uint8_t *p)
|
2011-11-04 22:28:50 +08:00
|
|
|
{
|
|
|
|
SECItem *sigitem = NULL;
|
|
|
|
|
|
|
|
if (num == 0) {
|
2013-08-29 00:31:47 +08:00
|
|
|
sigitem = pgpMpiItem(NULL, pgpsig->data, p);
|
2011-11-04 22:28:50 +08:00
|
|
|
if (sigitem)
|
|
|
|
pgpsig->data = sigitem;
|
|
|
|
}
|
|
|
|
return (sigitem == NULL);
|
|
|
|
}
|
|
|
|
|
2013-08-29 00:31:47 +08:00
|
|
|
static int pgpSetKeyMpiRSA(pgpDigAlg pgpkey, int num, const uint8_t *p)
|
2011-11-04 22:28:50 +08:00
|
|
|
{
|
|
|
|
SECItem *kitem = NULL;
|
|
|
|
SECKEYPublicKey *key = pgpkey->data;
|
|
|
|
|
|
|
|
if (key == NULL)
|
|
|
|
key = pgpkey->data = pgpNewPublicKey(rsaKey);
|
|
|
|
|
|
|
|
if (key) {
|
|
|
|
switch (num) {
|
|
|
|
case 0:
|
2013-08-29 00:31:47 +08:00
|
|
|
kitem = pgpMpiItem(key->arena, &key->u.rsa.modulus, p);
|
2011-11-04 22:28:50 +08:00
|
|
|
break;
|
|
|
|
case 1:
|
2013-08-29 00:31:47 +08:00
|
|
|
kitem = pgpMpiItem(key->arena, &key->u.rsa.publicExponent, p);
|
2011-11-04 22:28:50 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return (kitem == NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int pgpVerifySigRSA(pgpDigAlg pgpkey, pgpDigAlg pgpsig,
|
|
|
|
uint8_t *hash, size_t hashlen, int hash_algo)
|
|
|
|
{
|
|
|
|
SECItem digest = { .type = siBuffer, .data = hash, .len = hashlen };
|
|
|
|
SECItem *sig = pgpsig->data;
|
|
|
|
SECKEYPublicKey *key = pgpkey->data;
|
|
|
|
SECItem *padded = NULL;
|
2012-11-29 18:35:13 +08:00
|
|
|
SECOidTag encAlg = SEC_OID_PKCS1_RSA_ENCRYPTION;
|
|
|
|
SECOidTag hashAlg = getHashAlg(hash_algo);
|
2011-11-04 22:28:50 +08:00
|
|
|
SECStatus rc = SECFailure;
|
|
|
|
size_t siglen, padlen;
|
|
|
|
|
2012-11-29 18:35:13 +08:00
|
|
|
if (hashAlg == SEC_OID_UNKNOWN)
|
|
|
|
return 1;
|
2011-11-04 22:28:50 +08:00
|
|
|
|
|
|
|
/* Zero-pad signature to expected size if necessary */
|
|
|
|
siglen = SECKEY_SignatureLen(key);
|
|
|
|
padlen = siglen - sig->len;
|
|
|
|
if (padlen) {
|
|
|
|
padded = SECITEM_AllocItem(NULL, NULL, siglen);
|
|
|
|
if (padded == NULL)
|
|
|
|
return 1;
|
|
|
|
memset(padded->data, 0, padlen);
|
|
|
|
memcpy(padded->data + padlen, sig->data, sig->len);
|
|
|
|
sig = padded;
|
|
|
|
}
|
|
|
|
|
2012-11-29 18:35:13 +08:00
|
|
|
rc = VFY_VerifyDigestDirect(&digest, key, sig, encAlg, hashAlg, NULL);
|
2011-11-04 22:28:50 +08:00
|
|
|
|
|
|
|
if (padded)
|
|
|
|
SECITEM_ZfreeItem(padded, PR_TRUE);
|
|
|
|
|
|
|
|
return (rc != SECSuccess);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void pgpFreeSigRSADSA(pgpDigAlg sa)
|
|
|
|
{
|
|
|
|
SECITEM_ZfreeItem(sa->data, PR_TRUE);
|
|
|
|
sa->data = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void pgpFreeKeyRSADSA(pgpDigAlg ka)
|
|
|
|
{
|
|
|
|
SECKEY_DestroyPublicKey(ka->data);
|
|
|
|
ka->data = NULL;
|
|
|
|
}
|
|
|
|
|
2013-08-29 00:31:47 +08:00
|
|
|
static int pgpSetMpiNULL(pgpDigAlg pgpkey, int num, const uint8_t *p)
|
2011-11-04 22:28:50 +08:00
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int pgpVerifyNULL(pgpDigAlg pgpkey, pgpDigAlg pgpsig,
|
|
|
|
uint8_t *hash, size_t hashlen, int hash_algo)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
pgpDigAlg pgpPubkeyNew(int algo)
|
|
|
|
{
|
|
|
|
pgpDigAlg ka = xcalloc(1, sizeof(*ka));;
|
|
|
|
|
|
|
|
switch (algo) {
|
|
|
|
case PGPPUBKEYALGO_RSA:
|
|
|
|
ka->setmpi = pgpSetKeyMpiRSA;
|
|
|
|
ka->free = pgpFreeKeyRSADSA;
|
|
|
|
ka->mpis = 2;
|
|
|
|
break;
|
|
|
|
case PGPPUBKEYALGO_DSA:
|
|
|
|
ka->setmpi = pgpSetKeyMpiDSA;
|
|
|
|
ka->free = pgpFreeKeyRSADSA;
|
|
|
|
ka->mpis = 4;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ka->setmpi = pgpSetMpiNULL;
|
|
|
|
ka->mpis = -1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
ka->verify = pgpVerifyNULL; /* keys can't be verified */
|
|
|
|
|
|
|
|
return ka;
|
|
|
|
}
|
|
|
|
|
|
|
|
pgpDigAlg pgpSignatureNew(int algo)
|
|
|
|
{
|
|
|
|
pgpDigAlg sa = xcalloc(1, sizeof(*sa));
|
|
|
|
|
|
|
|
switch (algo) {
|
|
|
|
case PGPPUBKEYALGO_RSA:
|
|
|
|
sa->setmpi = pgpSetSigMpiRSA;
|
|
|
|
sa->free = pgpFreeSigRSADSA;
|
|
|
|
sa->verify = pgpVerifySigRSA;
|
|
|
|
sa->mpis = 1;
|
|
|
|
break;
|
|
|
|
case PGPPUBKEYALGO_DSA:
|
|
|
|
sa->setmpi = pgpSetSigMpiDSA;
|
|
|
|
sa->free = pgpFreeSigRSADSA;
|
|
|
|
sa->verify = pgpVerifySigDSA;
|
|
|
|
sa->mpis = 2;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
sa->setmpi = pgpSetMpiNULL;
|
|
|
|
sa->verify = pgpVerifyNULL;
|
|
|
|
sa->mpis = -1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return sa;
|
|
|
|
}
|
|
|
|
|