1
0
Fork 0

Feature: Added support for HMACs

This commit is contained in:
Philipp Schafft 2020-11-21 18:19:39 +00:00
parent a840f56b69
commit ee8b67b421
3 changed files with 188 additions and 0 deletions

View File

@ -14,6 +14,7 @@
#endif
#include <string.h>
#include <stdlib.h>
#include "digest.h"
#include "md5.h"
@ -45,7 +46,28 @@ struct digest_tag {
} state;
};
struct hmac_tag {
/* base object */
refobject_base_t __base;
digest_algo_t algo;
char *key;
size_t key_len;
digest_t * inner;
};
static void __hmac_free(refobject_t self, void **userdata)
{
hmac_t *hmac = REFOBJECT_TO_TYPE(self, hmac_t *);
free(hmac->key);
refobject_unref(hmac->inner);
}
REFOBJECT_DEFINE_TYPE(digest_t);
REFOBJECT_DEFINE_TYPE(hmac_t,
REFOBJECT_DEFINE_TYPE_FREE(__hmac_free)
);
#define ROTL64(qword, n) ((qword) << (n) ^ ((qword) >> (64 - (n))))
@ -463,3 +485,160 @@ ssize_t digest_length_bytes(digest_t *digest)
return digest_algo_length_bytes(digest->algo);
}
static size_t __digest_algo_blocklength(digest_algo_t algo)
{
switch (algo) {
case DIGEST_ALGO_MD5: return 64; break;
case DIGEST_ALGO_SHA3_224: return 144; break;
case DIGEST_ALGO_SHA3_256: return 136; break;
case DIGEST_ALGO_SHA3_384: return 104; break;
case DIGEST_ALGO_SHA3_512: return 72; break;
}
return 0;
}
hmac_t * hmac_new(digest_algo_t algo, const void *key, size_t keylen)
{
hmac_t *hmac;
size_t blocklen = __digest_algo_blocklength(algo);
char *keycopy = calloc(1, blocklen);
size_t i;
if (!blocklen)
return NULL;
if (keylen > blocklen) {
size_t digestlen = digest_algo_length_bytes(algo);
digest_t *digest = digest_new(algo);
if (!digest) {
free(keycopy);
return NULL;
}
if (digest_write(digest, key, keylen) != (ssize_t)keylen) {
refobject_unref(digest);
free(keycopy);
return NULL;
}
if (digest_read(digest, keycopy, digestlen) != (ssize_t)digestlen) {
refobject_unref(digest);
free(keycopy);
return NULL;
}
refobject_unref(digest);
} else {
memcpy(keycopy, key, keylen);
}
hmac = refobject_new__new(hmac_t, NULL, NULL, NULL);
if (!hmac)
return NULL;
hmac->algo = algo;
hmac->key = keycopy;
hmac->key_len = blocklen;
hmac->inner = digest_new(algo);
if (!hmac->inner) {
refobject_unref(hmac);
return NULL;
}
for (i = 0; i < blocklen; i++) {
char x = keycopy[i] ^ 0x36;
if (digest_write(hmac->inner, &x, 1) != 1) {
refobject_unref(hmac);
return NULL;
}
}
return hmac;
}
hmac_t * hmac_copy(hmac_t *hmac)
{
hmac_t *n;
if (!hmac)
return NULL;
n = refobject_new__new(hmac_t, NULL, NULL, NULL);
n->algo = hmac->algo;
n->key = malloc(n->key_len);
if (!n->key) {
refobject_unref(n);
return NULL;
}
memcpy(n->key, hmac->key, hmac->key_len);
n->key_len = hmac->key_len;
n->inner = digest_copy(hmac->inner);
if (!n->inner) {
refobject_unref(n);
return NULL;
}
return n;
}
ssize_t hmac_write(hmac_t *hmac, const void *data, size_t len)
{
if (!hmac)
return -1;
return digest_write(hmac->inner, data, len);
}
ssize_t hmac_read(hmac_t *hmac, void *buf, size_t len)
{
size_t digestlen;
digest_t *digest;
char *res;
size_t i;
ssize_t ret;
if (!hmac)
return -1;
digestlen = digest_algo_length_bytes(hmac->algo);
digest = digest_new(hmac->algo);
if (!digest)
return -1;
res = malloc(digestlen);
if (!res) {
refobject_unref(digest);
return -1;
}
for (i = 0; i < hmac->key_len; i++) {
char x = hmac->key[i] ^ 0x5C;
if (digest_write(digest, &x, 1) != 1) {
free(res);
refobject_unref(digest);
return -1;
}
}
if (digest_read(hmac->inner, res, digestlen) != (ssize_t)digestlen) {
free(res);
refobject_unref(digest);
return -1;
}
if (digest_write(digest, res, digestlen) != (ssize_t)digestlen) {
free(res);
refobject_unref(digest);
return -1;
}
ret = digest_read(digest, buf, len);
free(res);
refobject_unref(digest);
return ret;
}

View File

@ -12,6 +12,7 @@
#include "refobject.h"
REFOBJECT_FORWARD_TYPE(digest_t);
REFOBJECT_FORWARD_TYPE(hmac_t);
typedef enum {
DIGEST_ALGO_MD5,
@ -32,4 +33,10 @@ ssize_t digest_read(digest_t *digest, void *buf, size_t len);
/* Returns the digest size in bytes */
ssize_t digest_length_bytes(digest_t *digest);
hmac_t * hmac_new(digest_algo_t algo, const void *key, size_t keylen);
hmac_t * hmac_copy(hmac_t *hmac);
ssize_t hmac_write(hmac_t *hmac, const void *data, size_t len);
ssize_t hmac_read(hmac_t *hmac, void *buf, size_t len);
#endif

View File

@ -125,6 +125,7 @@ typedef struct listensocket_tag listensocket_t;
/* ---[ digest.[ch] ]--- */
typedef struct digest_tag digest_t;
typedef struct hmac_tag hmac_t;
/* ---[ navigation.[ch] ]--- */
@ -146,6 +147,7 @@ typedef union __attribute__ ((__transparent_union__)) {
listensocket_container_t *listensocket_container;
listensocket_t *listensocket;
digest_t *digest;
hmac_t *hmac;
mount_identifier_t *mount_identifier;
} refobject_t;
#else