csomh / source-git / rpm

Forked from source-git/rpm 4 years ago
Clone
2ff057
#include "system.h"
2ff057
2ff057
#include <beecrypt/beecrypt.h>
2ff057
#include <beecrypt/dsa.h>
2ff057
#include <beecrypt/endianness.h>
2ff057
#include <beecrypt/md5.h>
2ff057
#include <beecrypt/mp.h>
2ff057
#include <beecrypt/rsa.h>
2ff057
#include <beecrypt/rsapk.h>
2ff057
#include <beecrypt/sha1.h>
2ff057
#if HAVE_BEECRYPT_API_H
2ff057
#include <beecrypt/sha256.h>
2ff057
#include <beecrypt/sha384.h>
2ff057
#include <beecrypt/sha512.h>
2ff057
#endif
2ff057
2ff057
#include <rpm/rpmpgp.h>
2ff057
#include "rpmio/digest.h"
2ff057
#include "rpmio/rpmio_internal.h"
2ff057
#include "debug.h"
2ff057
2ff057
/**
2ff057
 * MD5/SHA1 digest private data.
2ff057
 */
2ff057
struct DIGEST_CTX_s {
2ff057
    rpmDigestFlags flags;	/*!< Bit(s) to control digest operation. */
2ff057
    int algo;			/*!< Used hash algorithm */
2ff057
    uint32_t datalen;		/*!< No. bytes in block of plaintext data. */
2ff057
    uint32_t paramlen;		/*!< No. bytes of digest parameters. */
2ff057
    uint32_t digestlen;		/*!< No. bytes of digest. */
2ff057
    void * param;		/*!< Digest parameters. */
2ff057
    int (*Reset) (void * param);	/*!< Digest initialize. */
2ff057
    int (*Update) (void * param, const byte * data, size_t size);	/*!< Digest transform. */
2ff057
    int (*Digest) (void * param, byte * digest);	/*!< Digest finish. */
2ff057
};
2ff057
2ff057
2ff057
/****************************  init   ************************************/
2ff057
2ff057
int rpmInitCrypto(void) {
2ff057
    return 0;
2ff057
}
2ff057
2ff057
int rpmFreeCrypto(void) {
2ff057
    return 0;
2ff057
}
2ff057
2ff057
/****************************  digest ************************************/
2ff057
2ff057
DIGEST_CTX rpmDigestDup(DIGEST_CTX octx)
2ff057
{
2ff057
    DIGEST_CTX nctx = NULL;
2ff057
    if (octx) {
2ff057
	nctx = memcpy(xcalloc(1, sizeof(*nctx)), octx, sizeof(*nctx));
2ff057
	nctx->param = memcpy(xcalloc(1, nctx->paramlen), octx->param, nctx->paramlen);
2ff057
    }
2ff057
    return nctx;
2ff057
}
2ff057
2ff057
size_t rpmDigestLength(int hashalgo)
2ff057
{
2ff057
    switch (hashalgo) {
2ff057
    case PGPHASHALGO_MD5:
2ff057
	return 16;
2ff057
    case PGPHASHALGO_SHA1:
2ff057
	return 20;
2ff057
#if HAVE_BEECRYPT_API_H
2ff057
    case PGPHASHALGO_SHA256:
2ff057
	return 32;
2ff057
    case PGPHASHALGO_SHA384:
2ff057
	return 48;
2ff057
    case PGPHASHALGO_SHA512:
2ff057
	return 64;
2ff057
#endif
2ff057
    default:
2ff057
	return 0;
2ff057
    }
2ff057
}
2ff057
2ff057
DIGEST_CTX rpmDigestInit(int hashalgo, rpmDigestFlags flags)
2ff057
{
2ff057
    DIGEST_CTX ctx = xcalloc(1, sizeof(*ctx));
2ff057
2ff057
    ctx->flags = flags;
2ff057
    ctx->algo = hashalgo;
2ff057
2ff057
    switch (hashalgo) {
2ff057
    case PGPHASHALGO_MD5:
2ff057
	ctx->digestlen = 16;
2ff057
	ctx->datalen = 64;
2ff057
	ctx->paramlen = sizeof(md5Param);
2ff057
	ctx->param = xcalloc(1, ctx->paramlen);
2ff057
	ctx->Reset = (void *) md5Reset;
2ff057
	ctx->Update = (void *) md5Update;
2ff057
	ctx->Digest = (void *) md5Digest;
2ff057
	break;
2ff057
    case PGPHASHALGO_SHA1:
2ff057
	ctx->digestlen = 20;
2ff057
	ctx->datalen = 64;
2ff057
	ctx->paramlen = sizeof(sha1Param);
2ff057
	ctx->param = xcalloc(1, ctx->paramlen);
2ff057
	ctx->Reset = (void *) sha1Reset;
2ff057
	ctx->Update = (void *) sha1Update;
2ff057
	ctx->Digest = (void *) sha1Digest;
2ff057
	break;
2ff057
#if HAVE_BEECRYPT_API_H
2ff057
    case PGPHASHALGO_SHA256:
2ff057
	ctx->digestlen = 32;
2ff057
	ctx->datalen = 64;
2ff057
	ctx->paramlen = sizeof(sha256Param);
2ff057
	ctx->param = xcalloc(1, ctx->paramlen);
2ff057
	ctx->Reset = (void *) sha256Reset;
2ff057
	ctx->Update = (void *) sha256Update;
2ff057
	ctx->Digest = (void *) sha256Digest;
2ff057
	break;
2ff057
    case PGPHASHALGO_SHA384:
2ff057
	ctx->digestlen = 48;
2ff057
	ctx->datalen = 128;
2ff057
	ctx->paramlen = sizeof(sha384Param);
2ff057
	ctx->param = xcalloc(1, ctx->paramlen);
2ff057
	ctx->Reset = (void *) sha384Reset;
2ff057
	ctx->Update = (void *) sha384Update;
2ff057
	ctx->Digest = (void *) sha384Digest;
2ff057
	break;
2ff057
    case PGPHASHALGO_SHA512:
2ff057
	ctx->digestlen = 64;
2ff057
	ctx->datalen = 128;
2ff057
	ctx->paramlen = sizeof(sha512Param);
2ff057
	ctx->param = xcalloc(1, ctx->paramlen);
2ff057
	ctx->Reset = (void *) sha512Reset;
2ff057
	ctx->Update = (void *) sha512Update;
2ff057
	ctx->Digest = (void *) sha512Digest;
2ff057
	break;
2ff057
#endif
2ff057
    case PGPHASHALGO_RIPEMD160:
2ff057
    case PGPHASHALGO_MD2:
2ff057
    case PGPHASHALGO_TIGER192:
2ff057
    case PGPHASHALGO_HAVAL_5_160:
2ff057
    default:
2ff057
	free(ctx);
2ff057
	return NULL;
2ff057
    }
2ff057
2ff057
    (*ctx->Reset)(ctx->param);
2ff057
    return ctx;
2ff057
}
2ff057
2ff057
int rpmDigestUpdate(DIGEST_CTX ctx, const void * data, size_t len)
2ff057
{
2ff057
    if (ctx == NULL)
2ff057
	return -1;
2ff057
2ff057
    return (*ctx->Update) (ctx->param, data, len);
2ff057
}
2ff057
2ff057
int rpmDigestFinal(DIGEST_CTX ctx, void ** datap, size_t *lenp, int asAscii)
2ff057
{
2ff057
    byte * digest;
2ff057
    char * t;
2ff057
    int i;
2ff057
2ff057
    if (ctx == NULL)
2ff057
	return -1;
2ff057
    digest = xmalloc(ctx->digestlen);
2ff057
2ff057
    /* FIX: check rc */
2ff057
    (void) (*ctx->Digest) (ctx->param, digest);
2ff057
2ff057
    /* Return final digest. */
2ff057
    if (!asAscii) {
2ff057
	if (lenp) *lenp = ctx->digestlen;
2ff057
	if (datap) {
2ff057
	    *datap = digest;
2ff057
	    digest = NULL;
2ff057
	}
2ff057
    } else {
2ff057
	if (lenp) *lenp = (2*ctx->digestlen) + 1;
2ff057
	if (datap) {
2ff057
	    const byte * s = (const byte *) digest;
2ff057
	    static const char hex[] = "0123456789abcdef";
2ff057
2ff057
	    *datap = t = xmalloc((2*ctx->digestlen) + 1);
2ff057
	    for (i = 0 ; i < ctx->digestlen; i++) {
2ff057
		*t++ = hex[ (unsigned)((*s >> 4) & 0x0f) ];
2ff057
		*t++ = hex[ (unsigned)((*s++   ) & 0x0f) ];
2ff057
	    }
2ff057
	    *t = '\0';
2ff057
	}
2ff057
    }
2ff057
    if (digest) {
2ff057
	memset(digest, 0, ctx->digestlen);	/* In case it's sensitive */
2ff057
	free(digest);
2ff057
    }
2ff057
    memset(ctx->param, 0, ctx->paramlen);	/* In case it's sensitive */
2ff057
    free(ctx->param);
2ff057
    memset(ctx, 0, sizeof(*ctx));	/* In case it's sensitive */
2ff057
    free(ctx);
2ff057
    return 0;
2ff057
}
2ff057
2ff057
2ff057
/****************************** RSA **************************************/
2ff057
2ff057
struct pgpDigSigRSA_s {
2ff057
    mpnumber c;
2ff057
};
2ff057
2ff057
struct pgpDigKeyRSA_s {
2ff057
    rsapk rsa_pk;
2ff057
    int nbytes;
2ff057
};
2ff057
2ff057
static int pgpSetSigMpiRSA(pgpDigAlg pgpsig, int num, const uint8_t *p)
2ff057
{
2ff057
    struct pgpDigSigRSA_s *sig = pgpsig->data;
2ff057
    int mlen = pgpMpiLen(p) - 2;
2ff057
    int rc = 1;
2ff057
2ff057
    if (!sig)
2ff057
	sig = pgpsig->data = xcalloc(1, sizeof(*sig));
2ff057
2ff057
    switch (num) {
2ff057
    case 0:
2ff057
	if (!mpnsetbin(&sig->c, p + 2, mlen))
2ff057
	    rc = 0;
2ff057
	break;
2ff057
    }
2ff057
    return rc;
2ff057
}
2ff057
2ff057
static int pgpSetKeyMpiRSA(pgpDigAlg pgpkey, int num, const uint8_t *p)
2ff057
{
2ff057
    struct pgpDigKeyRSA_s *key = pgpkey->data;
2ff057
    int mlen = pgpMpiLen(p) - 2;
2ff057
    int rc = 1;
2ff057
2ff057
    if (!key)
2ff057
	key = pgpkey->data = xcalloc(1, sizeof(*key));
2ff057
2ff057
    switch (num) {
2ff057
    case 0:
2ff057
	key->nbytes = mlen;
2ff057
	if (!mpbsetbin(&key->rsa_pk.n, p + 2, mlen))
2ff057
	    rc = 0;
2ff057
	break;
2ff057
    case 1:
2ff057
	if (!mpnsetbin(&key->rsa_pk.e, p + 2, mlen))
2ff057
	    rc = 0;
2ff057
	break;
2ff057
    }
2ff057
    return rc;
2ff057
}
2ff057
2ff057
static int pkcs1pad(mpnumber *rsahm, int nbytes, const char *prefix, uint8_t *hash, size_t hashlen)
2ff057
{
2ff057
    int datalen = strlen(prefix) / 2 + hashlen;
2ff057
    byte *buf, *bp;
2ff057
    int rc = 1;
2ff057
2ff057
    if (nbytes < 4 + datalen)
2ff057
	return 1;
2ff057
    buf = xmalloc(nbytes);
2ff057
    memset(buf, 0xff, nbytes);
2ff057
    buf[0] = 0x00;
2ff057
    buf[1] = 0x01;
2ff057
    bp = buf + nbytes - datalen;
2ff057
    bp[-1] = 0;
2ff057
    for (; *prefix; prefix += 2)
2ff057
	*bp++ = (rnibble(prefix[0]) << 4) | rnibble(prefix[1]);
2ff057
    memcpy(bp, hash, hashlen);
2ff057
    if (!mpnsetbin(rsahm, buf, nbytes))
2ff057
	rc = 0;
2ff057
    buf = _free(buf);
2ff057
    return rc;
2ff057
}
2ff057
2ff057
static int pgpVerifySigRSA(pgpDigAlg pgpkey, pgpDigAlg pgpsig, uint8_t *hash, size_t hashlen, int hash_algo)
2ff057
{
2ff057
    struct pgpDigKeyRSA_s *key = pgpkey->data;
2ff057
    struct pgpDigSigRSA_s *sig = pgpsig->data;
2ff057
    const char * prefix = NULL;
2ff057
    mpnumber rsahm;
2ff057
    int rc = 1;
2ff057
2ff057
    if (!sig || !key)
2ff057
	return rc;
2ff057
2ff057
    switch (hash_algo) {
2ff057
    case PGPHASHALGO_MD5:
2ff057
        prefix = "3020300c06082a864886f70d020505000410";
2ff057
        break;
2ff057
    case PGPHASHALGO_SHA1:
2ff057
        prefix = "3021300906052b0e03021a05000414";
2ff057
        break;
2ff057
    case PGPHASHALGO_MD2:
2ff057
        prefix = "3020300c06082a864886f70d020205000410";
2ff057
        break;
2ff057
    case PGPHASHALGO_SHA256:
2ff057
        prefix = "3031300d060960864801650304020105000420";
2ff057
        break;
2ff057
    case PGPHASHALGO_SHA384:
2ff057
        prefix = "3041300d060960864801650304020205000430";
2ff057
        break;
2ff057
    case PGPHASHALGO_SHA512:
2ff057
        prefix = "3051300d060960864801650304020305000440";
2ff057
        break;
2ff057
    default:
2ff057
	return 1;
2ff057
    }
2ff057
2ff057
    memset(&rsahm, 0, sizeof(rsahm));
2ff057
    if (pkcs1pad(&rsahm, key->nbytes, prefix, hash, hashlen) != 0)
2ff057
	return 1;
2ff057
2ff057
#if HAVE_BEECRYPT_API_H
2ff057
    rc = rsavrfy(&key->rsa_pk.n, &key->rsa_pk.e, &sig->c, &rsahm) == 1 ? 0 : 1;
2ff057
#else
2ff057
    rc = rsavrfy(&key->rsa_pk, &rsahm, &sig->c) == 1 ? 0 : 1;
2ff057
#endif
2ff057
    mpnfree(&rsahm);
2ff057
    return rc;
2ff057
}
2ff057
2ff057
static void pgpFreeSigRSA(pgpDigAlg pgpsig)
2ff057
{
2ff057
    struct pgpDigSigRSA_s *sig = pgpsig->data;
2ff057
    if (sig) {
2ff057
	mpnfree(&sig->c);
2ff057
	pgpsig->data = _free(sig);
2ff057
    }
2ff057
}
2ff057
2ff057
static void pgpFreeKeyRSA(pgpDigAlg pgpkey)
2ff057
{
2ff057
    struct pgpDigKeyRSA_s *key = pgpkey->data;
2ff057
    if (key) {
2ff057
	mpbfree(&key->rsa_pk.n);
2ff057
	mpnfree(&key->rsa_pk.e);
2ff057
	pgpkey->data = _free(key);
2ff057
    }
2ff057
}
2ff057
2ff057
2ff057
/****************************** DSA **************************************/
2ff057
2ff057
struct pgpDigSigDSA_s {
2ff057
    mpnumber r;
2ff057
    mpnumber s;
2ff057
};
2ff057
2ff057
struct pgpDigKeyDSA_s {
2ff057
    mpbarrett p;
2ff057
    mpbarrett q;
2ff057
    mpnumber g;
2ff057
    mpnumber y;
2ff057
    int qbytes;
2ff057
};
2ff057
2ff057
static int pgpSetSigMpiDSA(pgpDigAlg pgpsig, int num, const uint8_t *p)
2ff057
{
2ff057
    struct pgpDigSigDSA_s *sig = pgpsig->data;
2ff057
    int mlen = pgpMpiLen(p) - 2;
2ff057
    int rc = 1;
2ff057
2ff057
    if (!sig)
2ff057
	sig = pgpsig->data = xcalloc(1, sizeof(*sig));
2ff057
2ff057
    switch (num) {
2ff057
    case 0:
2ff057
	if (!mpnsetbin(&sig->r, p + 2, mlen))
2ff057
	    rc = 0;
2ff057
	break;
2ff057
    case 1:
2ff057
	if (!mpnsetbin(&sig->s, p + 2, mlen))
2ff057
	    rc = 0;
2ff057
	break;
2ff057
    }
2ff057
    return rc;
2ff057
}
2ff057
2ff057
static int pgpSetKeyMpiDSA(pgpDigAlg pgpkey, int num, const uint8_t *p)
2ff057
{
2ff057
    struct pgpDigKeyDSA_s *key = pgpkey->data;
2ff057
    int mlen = pgpMpiLen(p) - 2;
2ff057
    int rc = 1;
2ff057
2ff057
    if (!key)
2ff057
	key = pgpkey->data = xcalloc(1, sizeof(*key));
2ff057
2ff057
    switch (num) {
2ff057
    case 0:
2ff057
	if (!mpbsetbin(&key->p, p + 2, mlen))
2ff057
	    rc = 0;
2ff057
	break;
2ff057
    case 1:
2ff057
	key->qbytes = mlen;
2ff057
	if (!mpbsetbin(&key->q, p + 2, mlen))
2ff057
	    rc = 0;
2ff057
	break;
2ff057
    case 2:
2ff057
	if (!mpnsetbin(&key->g, p + 2, mlen))
2ff057
	    rc = 0;
2ff057
	break;
2ff057
    case 3:
2ff057
	if (!mpnsetbin(&key->y, p + 2, mlen))
2ff057
	    rc = 0;
2ff057
	break;
2ff057
    }
2ff057
    return rc;
2ff057
}
2ff057
2ff057
static int pgpVerifySigDSA(pgpDigAlg pgpkey, pgpDigAlg pgpsig, uint8_t *hash, size_t hashlen, int hash_algo)
2ff057
{
2ff057
    struct pgpDigKeyDSA_s *key = pgpkey->data;
2ff057
    struct pgpDigSigDSA_s *sig = pgpsig->data;
2ff057
    mpnumber hm;
2ff057
    int rc = 1;
2ff057
2ff057
    if (sig && key && hashlen >= key->qbytes) {
2ff057
	mpnzero(&hm;;
2ff057
	mpnsetbin(&hm, hash, key->qbytes);
2ff057
	rc = dsavrfy(&key->p, &key->q, &key->g, &hm, &key->y, &sig->r, &sig->s) == 1 ? 0 : 1;
2ff057
	mpnfree(&hm;;
2ff057
    }
2ff057
    return rc;
2ff057
}
2ff057
2ff057
static void pgpFreeSigDSA(pgpDigAlg pgpsig)
2ff057
{
2ff057
    struct pgpDigSigDSA_s *sig = pgpsig->data;
2ff057
    if (sig) {
2ff057
	mpnfree(&sig->r);
2ff057
	mpnfree(&sig->s);
2ff057
	pgpsig->data = _free(sig);
2ff057
    }
2ff057
}
2ff057
2ff057
static void pgpFreeKeyDSA(pgpDigAlg pgpkey)
2ff057
{
2ff057
    struct pgpDigKeyDSA_s *key = pgpkey->data;
2ff057
    if (key) {
2ff057
	mpbfree(&key->p);
2ff057
	mpbfree(&key->q);
2ff057
	mpnfree(&key->g);
2ff057
	mpnfree(&key->y);
2ff057
	pgpkey->data = _free(key);
2ff057
    }
2ff057
}
2ff057
2ff057
2ff057
/****************************** NULL **************************************/
2ff057
2ff057
static int pgpSetMpiNULL(pgpDigAlg pgpkey, int num, const uint8_t *p)
2ff057
{
2ff057
    return 1;
2ff057
}
2ff057
2ff057
static int pgpVerifyNULL(pgpDigAlg pgpkey, pgpDigAlg pgpsig,
2ff057
                         uint8_t *hash, size_t hashlen, int hash_algo)
2ff057
{
2ff057
    return 1;
2ff057
}
2ff057
2ff057
pgpDigAlg pgpPubkeyNew(int algo)
2ff057
{
2ff057
    pgpDigAlg ka = xcalloc(1, sizeof(*ka));;
2ff057
2ff057
    switch (algo) {
2ff057
    case PGPPUBKEYALGO_RSA:
2ff057
        ka->setmpi = pgpSetKeyMpiRSA;
2ff057
        ka->free = pgpFreeKeyRSA;
2ff057
        ka->mpis = 2;
2ff057
        break;
2ff057
    case PGPPUBKEYALGO_DSA:
2ff057
        ka->setmpi = pgpSetKeyMpiDSA;
2ff057
        ka->free = pgpFreeKeyDSA;
2ff057
        ka->mpis = 4;
2ff057
        break;
2ff057
    default:
2ff057
        ka->setmpi = pgpSetMpiNULL;
2ff057
        ka->mpis = -1;
2ff057
        break;
2ff057
    }
2ff057
2ff057
    ka->verify = pgpVerifyNULL; /* keys can't be verified */
2ff057
2ff057
    return ka;
2ff057
}
2ff057
2ff057
pgpDigAlg pgpSignatureNew(int algo)
2ff057
{
2ff057
    pgpDigAlg sa = xcalloc(1, sizeof(*sa));
2ff057
2ff057
    switch (algo) {
2ff057
    case PGPPUBKEYALGO_RSA:
2ff057
        sa->setmpi = pgpSetSigMpiRSA;
2ff057
        sa->free = pgpFreeSigRSA;
2ff057
        sa->verify = pgpVerifySigRSA;
2ff057
        sa->mpis = 1;
2ff057
        break;
2ff057
    case PGPPUBKEYALGO_DSA:
2ff057
        sa->setmpi = pgpSetSigMpiDSA;
2ff057
        sa->free = pgpFreeSigDSA;
2ff057
        sa->verify = pgpVerifySigDSA;
2ff057
        sa->mpis = 2;
2ff057
        break;
2ff057
    default:
2ff057
        sa->setmpi = pgpSetMpiNULL;
2ff057
        sa->verify = pgpVerifyNULL;
2ff057
        sa->mpis = -1;
2ff057
        break;
2ff057
    }
2ff057
    return sa;
2ff057
}