1 /* 2 * Copyright 2021-2022 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the Apache License 2.0 (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10 #include <stdio.h> 11 #include <stdlib.h> 12 #include <openssl/core_names.h> 13 #include <openssl/evp.h> 14 #include <openssl/params.h> 15 #include <openssl/err.h> 16 17 /* 18 * Taken from the test vector from the paper "SipHash: a fast short-input PRF". 19 * https://www.aumasson.jp/siphash/siphash.pdf 20 */ 21 22 /* 23 * Hard coding the key into an application is very bad. 24 * It is done here solely for educational purposes. 25 */ 26 static unsigned char key[] = { 27 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 28 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f 29 }; 30 31 static unsigned char data[] = { 32 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 33 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e 34 }; 35 36 static const unsigned char expected_output[] = { 37 0xe5, 0x45, 0xbe, 0x49, 0x61, 0xca, 0x29, 0xa1 38 }; 39 40 /* 41 * A property query used for selecting the SIPHASH implementation. 42 */ 43 static char *propq = NULL; 44 45 int main(int argc, char **argv) 46 { 47 int rv = EXIT_FAILURE; 48 EVP_MAC *mac = NULL; 49 EVP_MAC_CTX *mctx = NULL; 50 unsigned char out[8]; 51 OSSL_PARAM params[4], *p = params; 52 OSSL_LIB_CTX *library_context = NULL; 53 unsigned int digest_len = 8, c_rounds = 2, d_rounds = 4; 54 size_t out_len = 0; 55 56 library_context = OSSL_LIB_CTX_new(); 57 if (library_context == NULL) { 58 fprintf(stderr, "OSSL_LIB_CTX_new() returned NULL\n"); 59 goto end; 60 } 61 62 /* Fetch the SipHash implementation */ 63 mac = EVP_MAC_fetch(library_context, "SIPHASH", propq); 64 if (mac == NULL) { 65 fprintf(stderr, "EVP_MAC_fetch() returned NULL\n"); 66 goto end; 67 } 68 69 /* Create a context for the SipHash operation */ 70 mctx = EVP_MAC_CTX_new(mac); 71 if (mctx == NULL) { 72 fprintf(stderr, "EVP_MAC_CTX_new() returned NULL\n"); 73 goto end; 74 } 75 76 /* SipHash can support either 8 or 16-byte digests. */ 77 *p++ = OSSL_PARAM_construct_uint(OSSL_MAC_PARAM_SIZE, &digest_len); 78 79 /* 80 * The number of C-rounds and D-rounds is configurable. Standard SipHash 81 * uses values of 2 and 4 respectively. The following lines are unnecessary 82 * as they set the default, but demonstrate how to change these values. 83 */ 84 *p++ = OSSL_PARAM_construct_uint(OSSL_MAC_PARAM_C_ROUNDS, &c_rounds); 85 *p++ = OSSL_PARAM_construct_uint(OSSL_MAC_PARAM_D_ROUNDS, &d_rounds); 86 87 *p = OSSL_PARAM_construct_end(); 88 89 /* Initialise the SIPHASH operation */ 90 if (!EVP_MAC_init(mctx, key, sizeof(key), params)) { 91 fprintf(stderr, "EVP_MAC_init() failed\n"); 92 goto end; 93 } 94 95 /* Make one or more calls to process the data to be authenticated */ 96 if (!EVP_MAC_update(mctx, data, sizeof(data))) { 97 fprintf(stderr, "EVP_MAC_update() failed\n"); 98 goto end; 99 } 100 101 /* Make one call to the final to get the MAC */ 102 if (!EVP_MAC_final(mctx, out, &out_len, sizeof(out))) { 103 fprintf(stderr, "EVP_MAC_final() failed\n"); 104 goto end; 105 } 106 107 printf("Generated MAC:\n"); 108 BIO_dump_indent_fp(stdout, out, out_len, 2); 109 putchar('\n'); 110 111 if (out_len != sizeof(expected_output)) { 112 fprintf(stderr, "Generated MAC has an unexpected length\n"); 113 goto end; 114 } 115 116 if (CRYPTO_memcmp(expected_output, out, sizeof(expected_output)) != 0) { 117 fprintf(stderr, "Generated MAC does not match expected value\n"); 118 goto end; 119 } 120 121 rv = EXIT_SUCCESS; 122 end: 123 EVP_MAC_CTX_free(mctx); 124 EVP_MAC_free(mac); 125 OSSL_LIB_CTX_free(library_context); 126 if (rv != EXIT_SUCCESS) 127 ERR_print_errors_fp(stderr); 128 return rv; 129 } 130