sp800-108-kdf.c revision 1.2 1 1.1 christos /* $NetBSD: sp800-108-kdf.c,v 1.2 2017/01/28 21:31:49 christos Exp $ */
2 1.1 christos
3 1.1 christos /*
4 1.1 christos * Copyright (c) 2015, Secure Endpoints Inc.
5 1.1 christos * All rights reserved.
6 1.1 christos *
7 1.1 christos * Redistribution and use in source and binary forms, with or without
8 1.1 christos * modification, are permitted provided that the following conditions
9 1.1 christos * are met:
10 1.1 christos *
11 1.1 christos * - Redistributions of source code must retain the above copyright
12 1.1 christos * notice, this list of conditions and the following disclaimer.
13 1.1 christos *
14 1.1 christos * - Redistributions in binary form must reproduce the above copyright
15 1.1 christos * notice, this list of conditions and the following disclaimer in
16 1.1 christos * the documentation and/or other materials provided with the
17 1.1 christos * distribution.
18 1.1 christos *
19 1.1 christos * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 1.1 christos * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 1.1 christos * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 1.1 christos * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23 1.1 christos * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
24 1.1 christos * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25 1.1 christos * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 1.1 christos * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 1.1 christos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28 1.1 christos * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 1.1 christos * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
30 1.1 christos * OF THE POSSIBILITY OF SUCH DAMAGE.
31 1.1 christos *
32 1.1 christos */
33 1.1 christos
34 1.1 christos #include "krb5_locl.h"
35 1.1 christos
36 1.1 christos /*
37 1.1 christos * SP800-108 KDF
38 1.1 christos */
39 1.1 christos
40 1.1 christos /**
41 1.1 christos * As described in SP800-108 5.1 (for HMAC)
42 1.1 christos *
43 1.1 christos * @param context Kerberos 5 context
44 1.1 christos * @param kdf_K1 Base key material.
45 1.1 christos * @param kdf_label A string that identifies the purpose for the derived key.
46 1.1 christos * @param kdf_context A binary string containing parties, nonce, etc.
47 1.1 christos * @param md Message digest function to use for PRF.
48 1.1 christos * @param kdf_K0 Derived key data.
49 1.1 christos *
50 1.1 christos * @return Return an error code for an failure or 0 on success.
51 1.1 christos * @ingroup krb5_crypto
52 1.1 christos */
53 1.1 christos krb5_error_code
54 1.1 christos _krb5_SP800_108_HMAC_KDF(krb5_context context,
55 1.1 christos const krb5_data *kdf_K1,
56 1.1 christos const krb5_data *kdf_label,
57 1.1 christos const krb5_data *kdf_context,
58 1.1 christos const EVP_MD *md,
59 1.1 christos krb5_data *kdf_K0)
60 1.1 christos {
61 1.1 christos HMAC_CTX c;
62 1.1 christos unsigned char *p = kdf_K0->data;
63 1.1 christos size_t i, n, left = kdf_K0->length;
64 1.1 christos unsigned char hmac[EVP_MAX_MD_SIZE];
65 1.1 christos unsigned int h = EVP_MD_size(md);
66 1.1 christos const size_t L = kdf_K0->length;
67 1.1 christos
68 1.1 christos heim_assert(md != NULL, "SP800-108 KDF internal error");
69 1.1 christos
70 1.1 christos HMAC_CTX_init(&c);
71 1.1 christos
72 1.1 christos n = L / h;
73 1.1 christos
74 1.1 christos for (i = 0; i <= n; i++) {
75 1.1 christos unsigned char tmp[4];
76 1.1 christos size_t len;
77 1.1 christos
78 1.1 christos HMAC_Init_ex(&c, kdf_K1->data, kdf_K1->length, md, NULL);
79 1.1 christos
80 1.1 christos _krb5_put_int(tmp, i + 1, 4);
81 1.1 christos HMAC_Update(&c, tmp, 4);
82 1.1 christos HMAC_Update(&c, kdf_label->data, kdf_label->length);
83 1.1 christos HMAC_Update(&c, (unsigned char *)"", 1);
84 1.1 christos if (kdf_context)
85 1.1 christos HMAC_Update(&c, kdf_context->data, kdf_context->length);
86 1.1 christos _krb5_put_int(tmp, L * 8, 4);
87 1.1 christos HMAC_Update(&c, tmp, 4);
88 1.1 christos
89 1.1 christos HMAC_Final(&c, hmac, &h);
90 1.1 christos len = h > left ? left : h;
91 1.1 christos memcpy(p, hmac, len);
92 1.1 christos p += len;
93 1.1 christos left -= len;
94 1.1 christos }
95 1.1 christos
96 1.1 christos HMAC_CTX_cleanup(&c);
97 1.1 christos
98 1.1 christos return 0;
99 1.1 christos }
100