1 /* $OpenBSD: prf.c,v 1.15 2005/04/08 22:32:10 cloder 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 <sys/param.h>
34 #include <stdlib.h>
35 #include <string.h>
36
37 #include "hash.h"
38 #include "log.h"
39 #include "prf.h"
40
41 void prf_hash_init(struct prf_hash_ctx *);
42 void prf_hash_update(struct prf_hash_ctx *, unsigned char *, unsigned int);
43 void prf_hash_final(unsigned char *, struct prf_hash_ctx *);
44
45 /* PRF behaves likes a hash */
46
47 void
prf_hash_init(struct prf_hash_ctx * ctx)48 prf_hash_init(struct prf_hash_ctx *ctx)
49 {
50 memcpy(ctx->hash->ctx, ctx->ctx, ctx->hash->ctxsize);
51 memcpy(ctx->hash->ctx2, ctx->ctx2, ctx->hash->ctxsize);
52 }
53
54 void
prf_hash_update(struct prf_hash_ctx * ctx,unsigned char * data,unsigned int len)55 prf_hash_update(struct prf_hash_ctx *ctx, unsigned char *data,
56 unsigned int len)
57 {
58 ctx->hash->Update(ctx->hash->ctx, data, len);
59 }
60
61 void
prf_hash_final(unsigned char * digest,struct prf_hash_ctx * ctx)62 prf_hash_final(unsigned char *digest, struct prf_hash_ctx *ctx)
63 {
64 ctx->hash->HMACFinal(digest, ctx->hash);
65 }
66
67 /*
68 * Obtain a Pseudo-Random Function for us. At the moment this is
69 * the HMAC version of a hash. See RFC-2104 for reference.
70 */
71 struct prf *
prf_alloc(enum prfs type,int subtype,unsigned char * shared,unsigned int sharedsize)72 prf_alloc(enum prfs type, int subtype, unsigned char *shared,
73 unsigned int sharedsize)
74 {
75 struct hash *hash;
76 struct prf *prf;
77 struct prf_hash_ctx *prfctx;
78
79 switch (type) {
80 case PRF_HMAC:
81 hash = hash_get(subtype);
82 if (!hash) {
83 log_print("prf_alloc: unknown hash type %d", subtype);
84 return 0;
85 }
86 break;
87 default:
88 log_print("prf_alloc: unknown PRF type %d", type);
89 return 0;
90 }
91
92 prf = malloc(sizeof *prf);
93 if (!prf) {
94 log_error("prf_alloc: malloc (%lu) failed",
95 (unsigned long)sizeof *prf);
96 return 0;
97 }
98 if (type == PRF_HMAC) {
99 /* Obtain needed memory. */
100 prfctx = malloc(sizeof *prfctx);
101 if (!prfctx) {
102 log_error("prf_alloc: malloc (%lu) failed",
103 (unsigned long)sizeof *prfctx);
104 goto cleanprf;
105 }
106 prf->prfctx = prfctx;
107
108 prfctx->ctx = malloc(hash->ctxsize);
109 if (!prfctx->ctx) {
110 log_error("prf_alloc: malloc (%d) failed",
111 hash->ctxsize);
112 goto cleanprfctx;
113 }
114 prfctx->ctx2 = malloc(hash->ctxsize);
115 if (!prfctx->ctx2) {
116 log_error("prf_alloc: malloc (%d) failed",
117 hash->ctxsize);
118 free(prfctx->ctx);
119 goto cleanprfctx;
120 }
121 prf->type = PRF_HMAC;
122 prf->blocksize = hash->hashsize;
123 prfctx->hash = hash;
124
125 /* Use the correct function pointers. */
126 prf->Init = (void(*)(void *))prf_hash_init;
127 prf->Update = (void(*)(void *, unsigned char *,
128 unsigned int))prf_hash_update;
129 prf->Final = (void(*)(unsigned char *, void *))prf_hash_final;
130
131 /* Init HMAC contexts. */
132 hash->HMACInit(hash, shared, sharedsize);
133
134 /* Save contexts. */
135 memcpy(prfctx->ctx, hash->ctx, hash->ctxsize);
136 memcpy(prfctx->ctx2, hash->ctx2, hash->ctxsize);
137 }
138 return prf;
139
140 cleanprfctx:
141 free(prf->prfctx);
142 cleanprf:
143 free(prf);
144 return 0;
145 }
146
147 /* Deallocate the PRF pointed to by PRF. */
148 void
prf_free(struct prf * prf)149 prf_free(struct prf *prf)
150 {
151 struct prf_hash_ctx *prfctx = prf->prfctx;
152
153 if (prf->type == PRF_HMAC) {
154 free(prfctx->ctx2);
155 free(prfctx->ctx);
156 }
157 free(prf->prfctx);
158 free(prf);
159 }
160