blob: 3151cdb4fc5127f1526bc4e2d97face4851968b6 [file] [log] [blame]
#include <string.h>
#include "dnsmasq.h"
#include "dnssec-crypto.h"
#include <openssl/evp.h>
typedef struct VACTX_rsasha1
{
VerifyAlgCtx base;
unsigned char *sig;
unsigned siglen;
union
{
EVP_MD_CTX hash;
unsigned char digest[20];
};
} VACTX_rsasha1;
typedef struct VACTX_rsasha256
{
VerifyAlgCtx base;
unsigned char *sig;
unsigned siglen;
union
{
EVP_MD_CTX hash;
unsigned char digest[32];
};
} VACTX_rsasha256;
#define POOL_SIZE 1
static union _Pool
{
VACTX_rsasha1 rsasha1;
VACTX_rsasha256 rsasha256;
} Pool[POOL_SIZE];
static char pool_used = 0;
static int rsasha1_set_signature(VerifyAlgCtx *ctx_, unsigned char *data, unsigned len)
{
VACTX_rsasha1 *ctx = (VACTX_rsasha1 *)ctx_;
ctx->sig = data;
ctx->siglen = len;
return 1;
}
static int rsasha256_set_signature(VerifyAlgCtx *ctx_, unsigned char *data, unsigned len)
{
VACTX_rsasha256 *ctx = (VACTX_rsasha256 *)ctx_;
ctx->sig = data;
ctx->siglen = len;
return 1;
}
static void rsasha1_begin_data(VerifyAlgCtx *ctx_)
{
VACTX_rsasha1 *ctx = (VACTX_rsasha1 *)ctx_;
EVP_MD_CTX_init(&ctx->hash);
EVP_DigestInit_ex(&ctx->hash, EVP_sha1(), NULL);
}
static void rsasha256_begin_data(VerifyAlgCtx *ctx_)
{
VACTX_rsasha256 *ctx = (VACTX_rsasha256 *)ctx_;
EVP_MD_CTX_init(&ctx->hash);
EVP_DigestInit_ex(&ctx->hash, EVP_sha256(), NULL);
}
static void rsasha1_add_data(VerifyAlgCtx *ctx_, void *data, unsigned len)
{
VACTX_rsasha1 *ctx = (VACTX_rsasha1 *)ctx_;
EVP_DigestUpdate(&ctx->hash, data, len);
}
static void rsasha256_add_data(VerifyAlgCtx *ctx_, void *data, unsigned len)
{
VACTX_rsasha256 *ctx = (VACTX_rsasha256 *)ctx_;
EVP_DigestUpdate(&ctx->hash, data, len);
}
static void rsasha1_end_data(VerifyAlgCtx *ctx_)
{
VACTX_rsasha1 *ctx = (VACTX_rsasha1 *)ctx_;
unsigned char digest[20];
EVP_DigestFinal(&ctx->hash, digest, NULL);
memcpy(ctx->digest, digest, 20);
}
static void rsasha256_end_data(VerifyAlgCtx *ctx_)
{
VACTX_rsasha256 *ctx = (VACTX_rsasha256 *)ctx_;
unsigned char digest[32];
EVP_DigestFinal(&ctx->hash, digest, NULL);
memcpy(ctx->digest, digest, 32);
}
static int rsasha1_verify(VerifyAlgCtx *ctx_, unsigned char *key, unsigned key_len)
{
VACTX_rsasha1 *ctx = (VACTX_rsasha1 *)ctx_;
return 0;
}
static int rsasha256_verify(VerifyAlgCtx *ctx_, unsigned char *key, unsigned key_len)
{
VACTX_rsasha256 *ctx = (VACTX_rsasha256 *)ctx_;
return 0;
}
#define DEFINE_VALG(alg) \
int alg ## _set_signature(VerifyAlgCtx *ctx, unsigned char *data, unsigned len); \
void alg ## _begin_data(VerifyAlgCtx *ctx); \
void alg ## _add_data(VerifyAlgCtx *ctx, void *data, unsigned len); \
void alg ## _end_data(VerifyAlgCtx *ctx); \
int alg ## _verify(VerifyAlgCtx *ctx, unsigned char *key, unsigned key_len) \
/**/
#define VALG_VTABLE(alg) { \
alg ## _set_signature, \
alg ## _begin_data, \
alg ## _add_data, \
alg ## _end_data, \
alg ## _verify \
} /**/
DEFINE_VALG(rsasha1);
DEFINE_VALG(rsasha256);
/* Updated registry that merges various RFCs:
https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xml */
static const VerifyAlg valgs[] =
{
{0,0,0,0,0}, /* 0: reserved */
{0,0,0,0,0}, /* 1: RSAMD5 */
{0,0,0,0,0}, /* 2: DH */
{0,0,0,0,0}, /* 3: DSA */
{0,0,0,0,0}, /* 4: ECC */
VALG_VTABLE(rsasha1), /* 5: RSASHA1 */
{0,0,0,0,0}, /* 6: DSA-NSEC3-SHA1 */
{0,0,0,0,0}, /* 7: RSASHA1-NSEC3-SHA1 */
VALG_VTABLE(rsasha256), /* 8: RSASHA256 */
{0,0,0,0,0}, /* 9: unassigned */
{0,0,0,0,0}, /* 10: RSASHA512 */
{0,0,0,0,0}, /* 11: unassigned */
{0,0,0,0,0}, /* 12: ECC-GOST */
{0,0,0,0,0}, /* 13: ECDSAP256SHA256 */
{0,0,0,0,0}, /* 14: ECDSAP384SHA384 */
};
static const int valgctx_size[] =
{
0, /* 0: reserved */
0, /* 1: RSAMD5 */
0, /* 2: DH */
0, /* 3: DSA */
0, /* 4: ECC */
sizeof(VACTX_rsasha1), /* 5: RSASHA1 */
0, /* 6: DSA-NSEC3-SHA1 */
0, /* 7: RSASHA1-NSEC3-SHA1 */
sizeof(VACTX_rsasha256), /* 8: RSASHA256 */
0, /* 9: unassigned */
0, /* 10: RSASHA512 */
0, /* 11: unassigned */
0, /* 12: ECC-GOST */
0, /* 13: ECDSAP256SHA256 */
0, /* 14: ECDSAP384SHA384 */
};
int verifyalg_supported(int algo)
{
return (algo < countof(valgctx_size) && valgctx_size[algo] != 0);
}
VerifyAlgCtx* verifyalg_alloc(int algo)
{
int i;
VerifyAlgCtx *ret = 0;
if (!verifyalg_supported(algo))
return 0;
if (pool_used == (1<<POOL_SIZE)-1)
ret = whine_malloc(valgctx_size[algo]);
else
for (i = 0; i < POOL_SIZE; ++i)
if (!(pool_used & (1 << i)))
{
ret = &Pool[i];
pool_used |= 1 << i;
break;
}
if (ret)
ret->vtbl = &valgs[algo];
return ret;
}
void verifyalg_free(VerifyAlgCtx *a)
{
int pool_idx = ((char*)a - (char*)&Pool[0]) / sizeof(Pool[0]);
if (pool_idx < 0 || pool_idx >= POOL_SIZE)
{
free(a);
return;
}
pool_used &= ~(1 << pool_idx);
}
int verifyalg_algonum(VerifyAlgCtx *a)
{
int num = a->vtbl - valgs;
if (num < 0 || num >= countof(valgs))
return -1;
return num;
}