Fix packet authentication.
[tinc] / src / openssl / digest.c
index ff350da..f20a975 100644 (file)
 */
 
 #include "system.h"
+#include "utils.h"
+#include "xalloc.h"
 
 #include <openssl/err.h>
+#include <openssl/hmac.h>
 
 #include "digest.h"
 #include "logger.h"
@@ -35,6 +38,7 @@ static void set_maclength(digest_t *digest, int maclength) {
 
 bool digest_open_by_name(digest_t *digest, const char *name, int maclength) {
        digest->digest = EVP_get_digestbyname(name);
+       digest->key = NULL;
 
        if(!digest->digest) {
                logger(LOG_DEBUG, "Unknown digest name '%s'!", name);
@@ -47,6 +51,7 @@ bool digest_open_by_name(digest_t *digest, const char *name, int maclength) {
 
 bool digest_open_by_nid(digest_t *digest, int nid, int maclength) {
        digest->digest = EVP_get_digestbynid(nid);
+       digest->key = NULL;
 
        if(!digest->digest) {
                logger(LOG_DEBUG, "Unknown digest nid %d!", nid);
@@ -59,25 +64,39 @@ bool digest_open_by_nid(digest_t *digest, int nid, int maclength) {
 
 bool digest_open_sha1(digest_t *digest, int maclength) {
        digest->digest = EVP_sha1();
+       digest->key = NULL;
 
        set_maclength(digest, maclength);
        return true;
 }
 
+bool digest_set_key(digest_t *digest, const void *key, size_t len) {
+       digest->key = xrealloc(digest->key, len);
+       memcpy(digest->key, key, len);
+       digest->keylength = len;
+}
+
 void digest_close(digest_t *digest) {
+       if(digest->key)
+               free(digest->key);
+       digest->key = NULL;
 }
 
 bool digest_create(digest_t *digest, const void *indata, size_t inlen, void *outdata) {
        size_t len = EVP_MD_size(digest->digest);
        unsigned char tmpdata[len];
 
-       EVP_MD_CTX ctx;
-
-       if(!EVP_DigestInit(&ctx, digest->digest)
-                       || !EVP_DigestUpdate(&ctx, indata, inlen)
-                       || !EVP_DigestFinal(&ctx, tmpdata, NULL)) {
-               logger(LOG_DEBUG, "Error creating digest: %s", ERR_error_string(ERR_get_error(), NULL));
-               return false;
+       if(digest->key) {
+               HMAC(digest->digest, digest->key, digest->keylength, indata, inlen, tmpdata, NULL);
+       } else {
+               EVP_MD_CTX ctx;
+
+               if(!EVP_DigestInit(&ctx, digest->digest)
+                               || !EVP_DigestUpdate(&ctx, indata, inlen)
+                               || !EVP_DigestFinal(&ctx, tmpdata, NULL)) {
+                       logger(LOG_DEBUG, "Error creating digest: %s", ERR_error_string(ERR_get_error(), NULL));
+                       return false;
+               }
        }
 
        memcpy(outdata, tmpdata, digest->maclength);
@@ -85,7 +104,7 @@ bool digest_create(digest_t *digest, const void *indata, size_t inlen, void *out
 }
 
 bool digest_verify(digest_t *digest, const void *indata, size_t inlen, const void *cmpdata) {
-       size_t len = EVP_MD_size(digest->digest);
+       size_t len = digest->maclength;
        unsigned char outdata[len];
 
        return digest_create(digest, indata, inlen, outdata) && !memcmp(cmpdata, outdata, digest->maclength);