/src/opensc/openpace/src/eac_kdf.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2010-2012 Frank Morgner and Dominik Oepen |
3 | | * |
4 | | * This file is part of OpenPACE. |
5 | | * |
6 | | * OpenPACE is free software: you can redistribute it and/or modify it under |
7 | | * the terms of the GNU General Public License as published by the Free |
8 | | * Software Foundation, either version 3 of the License, or (at your option) |
9 | | * any later version. |
10 | | * |
11 | | * OpenPACE is distributed in the hope that it will be useful, but WITHOUT ANY |
12 | | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
13 | | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more |
14 | | * details. |
15 | | * |
16 | | * You should have received a copy of the GNU General Public License along with |
17 | | * OpenPACE. If not, see <http://www.gnu.org/licenses/>. |
18 | | * |
19 | | * Additional permission under GNU GPL version 3 section 7 |
20 | | * |
21 | | * If you modify this Program, or any covered work, by linking or combining it |
22 | | * with OpenSSL (or a modified version of that library), containing |
23 | | * parts covered by the terms of OpenSSL's license, the licensors of |
24 | | * this Program grant you additional permission to convey the resulting work. |
25 | | * Corresponding Source for a non-source form of such a combination shall include |
26 | | * the source code for the parts of OpenSSL used as well as that of the |
27 | | * covered work. |
28 | | * |
29 | | * If you modify this Program, or any covered work, by linking or combining it |
30 | | * with OpenSC (or a modified version of that library), containing |
31 | | * parts covered by the terms of OpenSC's license, the licensors of |
32 | | * this Program grant you additional permission to convey the resulting work. |
33 | | * Corresponding Source for a non-source form of such a combination shall include |
34 | | * the source code for the parts of OpenSC used as well as that of the |
35 | | * covered work. |
36 | | */ |
37 | | |
38 | | /** |
39 | | * @file eac_kdf.c |
40 | | * @brief Key derivation functions |
41 | | * |
42 | | * @author Frank Morgner <frankmorgner@gmail.com> |
43 | | * @author Dominik Oepen <oepen@informatik.hu-berlin.de> |
44 | | */ |
45 | | |
46 | | #ifdef HAVE_CONFIG_H |
47 | | #include "config.h" |
48 | | #endif |
49 | | |
50 | | #include "eac_err.h" |
51 | | #include "eac_kdf.h" |
52 | | #include "eac_util.h" |
53 | | #include "misc.h" |
54 | | #include "ssl_compat.h" |
55 | | #ifdef _WIN32 |
56 | | #include <winsock2.h> |
57 | | #else |
58 | | #include <arpa/inet.h> |
59 | | #endif |
60 | | #include <openssl/crypto.h> |
61 | | #include <string.h> |
62 | | |
63 | | BUF_MEM * |
64 | | kdf(const BUF_MEM *key, const BUF_MEM *nonce, const uint32_t counter, |
65 | | const KA_CTX *ka_ctx, EVP_MD_CTX *md_ctx) |
66 | 0 | { |
67 | 0 | size_t inlen, key_len; |
68 | 0 | BUF_MEM *in = NULL, *digest = NULL, *out = NULL; |
69 | |
|
70 | 0 | check((key && ka_ctx->md && ka_ctx->cipher), "Invalid arguments"); |
71 | |
|
72 | 0 | key_len = EVP_CIPHER_key_length(ka_ctx->cipher); |
73 | 0 | check(0 < EVP_MD_size(ka_ctx->md) |
74 | 0 | && key_len <= (size_t) EVP_MD_size(ka_ctx->md), |
75 | 0 | "Message digest not suitable for cipher"); |
76 | |
|
77 | 0 | in = BUF_MEM_new(); |
78 | 0 | check(in, "Failed to allocate memory"); |
79 | | |
80 | | /* Concatenate secret || nonce || counter |
81 | | * nonce is optional */ |
82 | 0 | if (nonce) { |
83 | 0 | inlen = key->length + nonce->length + sizeof counter; |
84 | 0 | check(BUF_MEM_grow(in, inlen), "Failed to allocate memory"); |
85 | 0 | memcpy(in->data, key->data, key->length); |
86 | 0 | memcpy(in->data + key->length, nonce->data, nonce->length); |
87 | 0 | memcpy(in->data + key->length + nonce->length, &counter, sizeof counter); |
88 | 0 | } else { |
89 | 0 | inlen = key->length + sizeof counter; |
90 | 0 | check(BUF_MEM_grow(in, inlen), "Failed to allocate memory"); |
91 | 0 | memcpy(in->data, key->data, key->length); |
92 | 0 | memcpy(in->data + key->length, &counter, sizeof counter); |
93 | 0 | } |
94 | | |
95 | 0 | digest = hash(ka_ctx->md, md_ctx, ka_ctx->md_engine, in); |
96 | 0 | check(digest, "Failed to compute hash"); |
97 | | |
98 | | /* Truncate the hash to the length of the key */ |
99 | 0 | out = BUF_MEM_create_init(digest->data, key_len); |
100 | |
|
101 | 0 | OPENSSL_cleanse(in->data, in->max); |
102 | 0 | BUF_MEM_free(in); |
103 | 0 | OPENSSL_cleanse(digest->data, digest->max); |
104 | 0 | BUF_MEM_free(digest); |
105 | |
|
106 | 0 | return out; |
107 | | |
108 | 0 | err: |
109 | 0 | if (in) { |
110 | 0 | OPENSSL_cleanse(in->data, in->max); |
111 | 0 | BUF_MEM_free(in); |
112 | 0 | } |
113 | |
|
114 | 0 | return NULL; |
115 | 0 | } |
116 | | |
117 | | BUF_MEM * |
118 | | kdf_pi(const PACE_SEC *pi, const BUF_MEM *nonce, const KA_CTX *ctx, EVP_MD_CTX *md_ctx) |
119 | 0 | { |
120 | 0 | BUF_MEM * out; |
121 | |
|
122 | 0 | out = kdf(pi->encoded, nonce, htonl(KDF_PI_COUNTER), ctx, md_ctx); |
123 | |
|
124 | 0 | return out; |
125 | 0 | } |
126 | | |
127 | | BUF_MEM * |
128 | | kdf_enc(const BUF_MEM *nonce, const KA_CTX *ctx, EVP_MD_CTX *md_ctx) |
129 | 0 | { |
130 | 0 | check_return(ctx, "Invalid arguments"); |
131 | |
|
132 | 0 | return kdf(ctx->shared_secret, nonce, htonl(KDF_ENC_COUNTER), ctx, md_ctx); |
133 | 0 | } |
134 | | |
135 | | BUF_MEM * |
136 | | kdf_mac(const BUF_MEM *nonce, const KA_CTX *ctx, EVP_MD_CTX *md_ctx) |
137 | 0 | { |
138 | 0 | check_return(ctx, "Invalid arguments"); |
139 | |
|
140 | | return kdf(ctx->shared_secret, nonce, htonl(KDF_MAC_COUNTER), ctx, md_ctx); |
141 | 0 | } |