1/* $OpenBSD: prf.c,v 1.16 2013/03/21 04:30:14 deraadt Exp $ */ 2/* $EOM: prf.c,v 1.7 1999/05/02 12:50:29 niklas Exp $ */ 3 4/* 5 * Copyright (c) 1998 Niels Provos. All rights reserved. 6 * Copyright (c) 1999 Niklas Hallqvist. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29/* 30 * This code was written under funding by Ericsson Radio Systems. 31 */ 32 33#include <stdlib.h> 34#include <string.h> 35 36#include "hash.h" 37#include "log.h" 38#include "prf.h" 39 40void prf_hash_init(struct prf_hash_ctx *); 41void prf_hash_update(struct prf_hash_ctx *, unsigned char *, unsigned int); 42void prf_hash_final(unsigned char *, struct prf_hash_ctx *); 43 44/* PRF behaves likes a hash */ 45 46void 47prf_hash_init(struct prf_hash_ctx *ctx) 48{ 49 memcpy(ctx->hash->ctx, ctx->ctx, ctx->hash->ctxsize); 50 memcpy(ctx->hash->ctx2, ctx->ctx2, ctx->hash->ctxsize); 51} 52 53void 54prf_hash_update(struct prf_hash_ctx *ctx, unsigned char *data, 55 unsigned int len) 56{ 57 ctx->hash->Update(ctx->hash->ctx, data, len); 58} 59 60void 61prf_hash_final(unsigned char *digest, struct prf_hash_ctx *ctx) 62{ 63 ctx->hash->HMACFinal(digest, ctx->hash); 64} 65 66/* 67 * Obtain a Pseudo-Random Function for us. At the moment this is 68 * the HMAC version of a hash. See RFC-2104 for reference. 69 */ 70struct prf * 71prf_alloc(enum prfs type, int subtype, unsigned char *shared, 72 unsigned int sharedsize) 73{ 74 struct hash *hash; 75 struct prf *prf; 76 struct prf_hash_ctx *prfctx; 77 78 switch (type) { 79 case PRF_HMAC: 80 hash = hash_get(subtype); 81 if (!hash) { 82 log_print("prf_alloc: unknown hash type %d", subtype); 83 return 0; 84 } 85 break; 86 default: 87 log_print("prf_alloc: unknown PRF type %d", type); 88 return 0; 89 } 90 91 prf = malloc(sizeof *prf); 92 if (!prf) { 93 log_error("prf_alloc: malloc (%lu) failed", 94 (unsigned long)sizeof *prf); 95 return 0; 96 } 97 if (type == PRF_HMAC) { 98 /* Obtain needed memory. */ 99 prfctx = malloc(sizeof *prfctx); 100 if (!prfctx) { 101 log_error("prf_alloc: malloc (%lu) failed", 102 (unsigned long)sizeof *prfctx); 103 goto cleanprf; 104 } 105 prf->prfctx = prfctx; 106 107 prfctx->ctx = malloc(hash->ctxsize); 108 if (!prfctx->ctx) { 109 log_error("prf_alloc: malloc (%d) failed", 110 hash->ctxsize); 111 goto cleanprfctx; 112 } 113 prfctx->ctx2 = malloc(hash->ctxsize); 114 if (!prfctx->ctx2) { 115 log_error("prf_alloc: malloc (%d) failed", 116 hash->ctxsize); 117 free(prfctx->ctx); 118 goto cleanprfctx; 119 } 120 prf->type = PRF_HMAC; 121 prf->blocksize = hash->hashsize; 122 prfctx->hash = hash; 123 124 /* Use the correct function pointers. */ 125 prf->Init = (void(*)(void *))prf_hash_init; 126 prf->Update = (void(*)(void *, unsigned char *, 127 unsigned int))prf_hash_update; 128 prf->Final = (void(*)(unsigned char *, void *))prf_hash_final; 129 130 /* Init HMAC contexts. */ 131 hash->HMACInit(hash, shared, sharedsize); 132 133 /* Save contexts. */ 134 memcpy(prfctx->ctx, hash->ctx, hash->ctxsize); 135 memcpy(prfctx->ctx2, hash->ctx2, hash->ctxsize); 136 } 137 return prf; 138 139cleanprfctx: 140 free(prf->prfctx); 141cleanprf: 142 free(prf); 143 return 0; 144} 145 146/* Deallocate the PRF pointed to by PRF. */ 147void 148prf_free(struct prf *prf) 149{ 150 struct prf_hash_ctx *prfctx = prf->prfctx; 151 152 if (prf->type == PRF_HMAC) { 153 free(prfctx->ctx2); 154 free(prfctx->ctx); 155 } 156 free(prf->prfctx); 157 free(prf); 158} 159