1*a079e38bSJohn Baldwin /* 2*a079e38bSJohn Baldwin * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. 3*a079e38bSJohn Baldwin * 4*a079e38bSJohn Baldwin * Licensed under the OpenSSL license (the "License"). You may not use 5*a079e38bSJohn Baldwin * this file except in compliance with the License. You can obtain a copy 6*a079e38bSJohn Baldwin * in the file LICENSE in the source distribution or at 7*a079e38bSJohn Baldwin * https://www.openssl.org/source/license.html 8*a079e38bSJohn Baldwin */ 9*a079e38bSJohn Baldwin 10*a079e38bSJohn Baldwin #include <sys/libkern.h> 11*a079e38bSJohn Baldwin #include <sys/malloc.h> 12*a079e38bSJohn Baldwin 13*a079e38bSJohn Baldwin #include <opencrypto/cryptodev.h> 14*a079e38bSJohn Baldwin #include <opencrypto/xform_auth.h> 15*a079e38bSJohn Baldwin 16*a079e38bSJohn Baldwin #include <crypto/openssl/ossl.h> 17*a079e38bSJohn Baldwin #include <crypto/openssl/ossl_poly1305.h> 18*a079e38bSJohn Baldwin 19*a079e38bSJohn Baldwin #define POLY1305_ASM 20*a079e38bSJohn Baldwin 21*a079e38bSJohn Baldwin /* From crypto/poly1305/poly1305.c */ 22*a079e38bSJohn Baldwin 23*a079e38bSJohn Baldwin /* pick 32-bit unsigned integer in little endian order */ 24*a079e38bSJohn Baldwin static unsigned int U8TOU32(const unsigned char *p) 25*a079e38bSJohn Baldwin { 26*a079e38bSJohn Baldwin return (((unsigned int)(p[0] & 0xff)) | 27*a079e38bSJohn Baldwin ((unsigned int)(p[1] & 0xff) << 8) | 28*a079e38bSJohn Baldwin ((unsigned int)(p[2] & 0xff) << 16) | 29*a079e38bSJohn Baldwin ((unsigned int)(p[3] & 0xff) << 24)); 30*a079e38bSJohn Baldwin } 31*a079e38bSJohn Baldwin 32*a079e38bSJohn Baldwin /* 33*a079e38bSJohn Baldwin * Implementations can be classified by amount of significant bits in 34*a079e38bSJohn Baldwin * words making up the multi-precision value, or in other words radix 35*a079e38bSJohn Baldwin * or base of numerical representation, e.g. base 2^64, base 2^32, 36*a079e38bSJohn Baldwin * base 2^26. Complementary characteristic is how wide is the result of 37*a079e38bSJohn Baldwin * multiplication of pair of digits, e.g. it would take 128 bits to 38*a079e38bSJohn Baldwin * accommodate multiplication result in base 2^64 case. These are used 39*a079e38bSJohn Baldwin * interchangeably. To describe implementation that is. But interface 40*a079e38bSJohn Baldwin * is designed to isolate this so that low-level primitives implemented 41*a079e38bSJohn Baldwin * in assembly can be self-contained/self-coherent. 42*a079e38bSJohn Baldwin */ 43*a079e38bSJohn Baldwin int poly1305_init(void *ctx, const unsigned char key[16], void *func); 44*a079e38bSJohn Baldwin void poly1305_blocks(void *ctx, const unsigned char *inp, size_t len, 45*a079e38bSJohn Baldwin unsigned int padbit); 46*a079e38bSJohn Baldwin void poly1305_emit(void *ctx, unsigned char mac[16], 47*a079e38bSJohn Baldwin const unsigned int nonce[4]); 48*a079e38bSJohn Baldwin 49*a079e38bSJohn Baldwin static void Poly1305_Init(POLY1305 *ctx, const unsigned char key[32]) 50*a079e38bSJohn Baldwin { 51*a079e38bSJohn Baldwin ctx->nonce[0] = U8TOU32(&key[16]); 52*a079e38bSJohn Baldwin ctx->nonce[1] = U8TOU32(&key[20]); 53*a079e38bSJohn Baldwin ctx->nonce[2] = U8TOU32(&key[24]); 54*a079e38bSJohn Baldwin ctx->nonce[3] = U8TOU32(&key[28]); 55*a079e38bSJohn Baldwin 56*a079e38bSJohn Baldwin /* 57*a079e38bSJohn Baldwin * Unlike reference poly1305_init assembly counterpart is expected 58*a079e38bSJohn Baldwin * to return a value: non-zero if it initializes ctx->func, and zero 59*a079e38bSJohn Baldwin * otherwise. Latter is to simplify assembly in cases when there no 60*a079e38bSJohn Baldwin * multiple code paths to switch between. 61*a079e38bSJohn Baldwin */ 62*a079e38bSJohn Baldwin if (!poly1305_init(ctx->opaque, key, &ctx->func)) { 63*a079e38bSJohn Baldwin ctx->func.blocks = poly1305_blocks; 64*a079e38bSJohn Baldwin ctx->func.emit = poly1305_emit; 65*a079e38bSJohn Baldwin } 66*a079e38bSJohn Baldwin 67*a079e38bSJohn Baldwin ctx->num = 0; 68*a079e38bSJohn Baldwin 69*a079e38bSJohn Baldwin } 70*a079e38bSJohn Baldwin 71*a079e38bSJohn Baldwin #ifdef POLY1305_ASM 72*a079e38bSJohn Baldwin /* 73*a079e38bSJohn Baldwin * This "eclipses" poly1305_blocks and poly1305_emit, but it's 74*a079e38bSJohn Baldwin * conscious choice imposed by -Wshadow compiler warnings. 75*a079e38bSJohn Baldwin */ 76*a079e38bSJohn Baldwin # define poly1305_blocks (*poly1305_blocks_p) 77*a079e38bSJohn Baldwin # define poly1305_emit (*poly1305_emit_p) 78*a079e38bSJohn Baldwin #endif 79*a079e38bSJohn Baldwin 80*a079e38bSJohn Baldwin static void Poly1305_Update(POLY1305 *ctx, const unsigned char *inp, size_t len) 81*a079e38bSJohn Baldwin { 82*a079e38bSJohn Baldwin #ifdef POLY1305_ASM 83*a079e38bSJohn Baldwin /* 84*a079e38bSJohn Baldwin * As documented, poly1305_blocks is never called with input 85*a079e38bSJohn Baldwin * longer than single block and padbit argument set to 0. This 86*a079e38bSJohn Baldwin * property is fluently used in assembly modules to optimize 87*a079e38bSJohn Baldwin * padbit handling on loop boundary. 88*a079e38bSJohn Baldwin */ 89*a079e38bSJohn Baldwin poly1305_blocks_f poly1305_blocks_p = ctx->func.blocks; 90*a079e38bSJohn Baldwin #endif 91*a079e38bSJohn Baldwin size_t rem, num; 92*a079e38bSJohn Baldwin 93*a079e38bSJohn Baldwin if ((num = ctx->num)) { 94*a079e38bSJohn Baldwin rem = POLY1305_BLOCK_SIZE - num; 95*a079e38bSJohn Baldwin if (len >= rem) { 96*a079e38bSJohn Baldwin memcpy(ctx->data + num, inp, rem); 97*a079e38bSJohn Baldwin poly1305_blocks(ctx->opaque, ctx->data, POLY1305_BLOCK_SIZE, 1); 98*a079e38bSJohn Baldwin inp += rem; 99*a079e38bSJohn Baldwin len -= rem; 100*a079e38bSJohn Baldwin } else { 101*a079e38bSJohn Baldwin /* Still not enough data to process a block. */ 102*a079e38bSJohn Baldwin memcpy(ctx->data + num, inp, len); 103*a079e38bSJohn Baldwin ctx->num = num + len; 104*a079e38bSJohn Baldwin return; 105*a079e38bSJohn Baldwin } 106*a079e38bSJohn Baldwin } 107*a079e38bSJohn Baldwin 108*a079e38bSJohn Baldwin rem = len % POLY1305_BLOCK_SIZE; 109*a079e38bSJohn Baldwin len -= rem; 110*a079e38bSJohn Baldwin 111*a079e38bSJohn Baldwin if (len >= POLY1305_BLOCK_SIZE) { 112*a079e38bSJohn Baldwin poly1305_blocks(ctx->opaque, inp, len, 1); 113*a079e38bSJohn Baldwin inp += len; 114*a079e38bSJohn Baldwin } 115*a079e38bSJohn Baldwin 116*a079e38bSJohn Baldwin if (rem) 117*a079e38bSJohn Baldwin memcpy(ctx->data, inp, rem); 118*a079e38bSJohn Baldwin 119*a079e38bSJohn Baldwin ctx->num = rem; 120*a079e38bSJohn Baldwin } 121*a079e38bSJohn Baldwin 122*a079e38bSJohn Baldwin static void Poly1305_Final(POLY1305 *ctx, unsigned char mac[16]) 123*a079e38bSJohn Baldwin { 124*a079e38bSJohn Baldwin #ifdef POLY1305_ASM 125*a079e38bSJohn Baldwin poly1305_blocks_f poly1305_blocks_p = ctx->func.blocks; 126*a079e38bSJohn Baldwin poly1305_emit_f poly1305_emit_p = ctx->func.emit; 127*a079e38bSJohn Baldwin #endif 128*a079e38bSJohn Baldwin size_t num; 129*a079e38bSJohn Baldwin 130*a079e38bSJohn Baldwin if ((num = ctx->num)) { 131*a079e38bSJohn Baldwin ctx->data[num++] = 1; /* pad bit */ 132*a079e38bSJohn Baldwin while (num < POLY1305_BLOCK_SIZE) 133*a079e38bSJohn Baldwin ctx->data[num++] = 0; 134*a079e38bSJohn Baldwin poly1305_blocks(ctx->opaque, ctx->data, POLY1305_BLOCK_SIZE, 0); 135*a079e38bSJohn Baldwin } 136*a079e38bSJohn Baldwin 137*a079e38bSJohn Baldwin poly1305_emit(ctx->opaque, mac, ctx->nonce); 138*a079e38bSJohn Baldwin 139*a079e38bSJohn Baldwin /* zero out the state */ 140*a079e38bSJohn Baldwin OPENSSL_cleanse(ctx, sizeof(*ctx)); 141*a079e38bSJohn Baldwin } 142*a079e38bSJohn Baldwin 143*a079e38bSJohn Baldwin static void 144*a079e38bSJohn Baldwin ossl_poly1305_init(void *vctx) 145*a079e38bSJohn Baldwin { 146*a079e38bSJohn Baldwin } 147*a079e38bSJohn Baldwin 148*a079e38bSJohn Baldwin static void 149*a079e38bSJohn Baldwin ossl_poly1305_setkey(void *vctx, const uint8_t *key, u_int klen) 150*a079e38bSJohn Baldwin { 151*a079e38bSJohn Baldwin MPASS(klen == 32); 152*a079e38bSJohn Baldwin Poly1305_Init(vctx, key); 153*a079e38bSJohn Baldwin } 154*a079e38bSJohn Baldwin 155*a079e38bSJohn Baldwin static int 156*a079e38bSJohn Baldwin ossl_poly1305_update(void *vctx, const void *buf, u_int len) 157*a079e38bSJohn Baldwin { 158*a079e38bSJohn Baldwin Poly1305_Update(vctx, buf, len); 159*a079e38bSJohn Baldwin return (0); 160*a079e38bSJohn Baldwin } 161*a079e38bSJohn Baldwin 162*a079e38bSJohn Baldwin static void 163*a079e38bSJohn Baldwin ossl_poly1305_final(uint8_t *digest, void *vctx) 164*a079e38bSJohn Baldwin { 165*a079e38bSJohn Baldwin Poly1305_Final(vctx, digest); 166*a079e38bSJohn Baldwin } 167*a079e38bSJohn Baldwin 168*a079e38bSJohn Baldwin struct auth_hash ossl_hash_poly1305 = { 169*a079e38bSJohn Baldwin .type = CRYPTO_POLY1305, 170*a079e38bSJohn Baldwin .name = "OpenSSL-Poly1305", 171*a079e38bSJohn Baldwin .hashsize = POLY1305_HASH_LEN, 172*a079e38bSJohn Baldwin .ctxsize = sizeof(struct poly1305_context), 173*a079e38bSJohn Baldwin .blocksize = POLY1305_BLOCK_SIZE, 174*a079e38bSJohn Baldwin .Init = ossl_poly1305_init, 175*a079e38bSJohn Baldwin .Setkey = ossl_poly1305_setkey, 176*a079e38bSJohn Baldwin .Update = ossl_poly1305_update, 177*a079e38bSJohn Baldwin .Final = ossl_poly1305_final, 178*a079e38bSJohn Baldwin }; 179*a079e38bSJohn Baldwin 180*a079e38bSJohn Baldwin _Static_assert(sizeof(struct poly1305_context) <= 181*a079e38bSJohn Baldwin sizeof(struct ossl_hash_context), "ossl_hash_context too small"); 182