pal_hmac.c 3.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

#include "pal_config.h"
#include "pal_utilities.h"
#include "pal_hmac.h"

#include <assert.h>

HMAC_CTX* CryptoNative_HmacCreate(const uint8_t* key, int32_t keyLen, const EVP_MD* md)
{
    assert(key != NULL || keyLen == 0);
    assert(keyLen >= 0);
    assert(md != NULL);

16
    HMAC_CTX* ctx = HMAC_CTX_new();
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
    if (ctx == NULL)
    {
        // Allocation failed
        return NULL;
    }

    // NOTE: We can't pass NULL as empty key since HMAC_Init_ex will interpret
    // that as request to reuse the "existing" key.
    uint8_t _;
    if (keyLen == 0)
        key = &_;

    int ret = HMAC_Init_ex(ctx, key, keyLen, md, NULL);

    if (!ret)
    {
33
        HMAC_CTX_free(ctx);
34 35 36 37 38 39 40 41 42 43
        return NULL;
    }

    return ctx;
}

void CryptoNative_HmacDestroy(HMAC_CTX* ctx)
{
    if (ctx != NULL)
    {
44
        HMAC_CTX_free(ctx);
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
    }
}

int32_t CryptoNative_HmacReset(HMAC_CTX* ctx)
{
    assert(ctx != NULL);

    return HMAC_Init_ex(ctx, NULL, 0, NULL, NULL);
}

int32_t CryptoNative_HmacUpdate(HMAC_CTX* ctx, const uint8_t* data, int32_t len)
{
    assert(ctx != NULL);
    assert(data != NULL || len == 0);
    assert(len >= 0);

    if (len < 0)
    {
        return 0;
    }

    return HMAC_Update(ctx, data, Int32ToSizeT(len));
}

int32_t CryptoNative_HmacFinal(HMAC_CTX* ctx, uint8_t* md, int32_t* len)
{
    assert(ctx != NULL);
    assert(len != NULL);
    assert(md != NULL || *len == 0);
    assert(*len >= 0);

    if (len == NULL || *len < 0)
    {
        return 0;
    }

    unsigned int unsignedLen = Int32ToUint32(*len);
    int ret = HMAC_Final(ctx, md, &unsignedLen);
    *len = Uint32ToInt32(unsignedLen);
    return ret;
}
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132

static HMAC_CTX* CryptoNative_HmacDup(const HMAC_CTX* ctx)
{
    assert(ctx != NULL);

    HMAC_CTX* dup = HMAC_CTX_new();

    if (dup == NULL)
    {
        return NULL;
    }

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wcast-qual"
    if (!HMAC_CTX_copy(dup, (HMAC_CTX*)ctx))
#pragma clang diagnostic pop
    {
        HMAC_CTX_free(dup);
        return NULL;
    }

    return dup;
}

int32_t CryptoNative_HmacCurrent(const HMAC_CTX* ctx, uint8_t* md, int32_t* len)
{
    assert(ctx != NULL);
    assert(len != NULL);
    assert(md != NULL || *len == 0);
    assert(*len >= 0);

    if (len == NULL || *len < 0)
    {
        return 0;
    }

    HMAC_CTX* dup = CryptoNative_HmacDup(ctx);

    if (dup != NULL)
    {
        int ret = CryptoNative_HmacFinal(dup, md, len);
        HMAC_CTX_free(dup);
        return ret;
    }

    return 0;
}
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165

int32_t CryptoNative_HmacOneShot(const EVP_MD* type,
                                 const uint8_t* key,
                                 int32_t keySize,
                                 const uint8_t* source,
                                 int32_t sourceSize,
                                 uint8_t* md,
                                 int32_t* mdSize)
{
    assert(mdSize != NULL && type != NULL && md != NULL && mdSize != NULL);
    assert(keySize >= 0 && *mdSize >= 0);
    assert(key != NULL || keySize == 0);
    assert(source != NULL || sourceSize == 0);

    uint8_t empty = 0;

    if (key == NULL)
    {
        if (keySize != 0)
        {
            return -1;
        }

        key = &empty;
    }

    unsigned int unsignedSource = Int32ToUint32(sourceSize);
    unsigned int unsignedSize = Int32ToUint32(*mdSize);
    unsigned char* result = HMAC(type, key, keySize, source, unsignedSource, md, &unsignedSize);
    *mdSize = Uint32ToInt32(unsignedSize);

    return result == NULL ? 0 : 1;
}