Annotation of embedaddon/strongswan/src/libstrongswan/credentials/containers/pkcs12.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2013 Tobias Brunner
3: * HSR Hochschule fuer Technik Rapperswil
4: *
5: * This program is free software; you can redistribute it and/or modify it
6: * under the terms of the GNU General Public License as published by the
7: * Free Software Foundation; either version 2 of the License, or (at your
8: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9: *
10: * This program is distributed in the hope that it will be useful, but
11: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13: * for more details.
14: */
15:
16: #include "pkcs12.h"
17:
18: #include <library.h>
19: #include <utils/debug.h>
20:
21: /**
22: * v * ceiling(len/v)
23: */
24: #define PKCS12_LEN(len, v) (((len) + v-1) & ~(v-1))
25:
26: /**
27: * Copy src to dst as many times as possible
28: */
29: static inline void copy_chunk(chunk_t dst, chunk_t src)
30: {
31: size_t i;
32:
33: for (i = 0; i < dst.len; i++)
34: {
35: dst.ptr[i] = src.ptr[i % src.len];
36: }
37: }
38:
39: /**
40: * Treat two chunks as integers in network order and add them together.
41: * The result is stored in the first chunk, if the second chunk is longer or the
42: * result overflows this is ignored.
43: */
44: static void add_chunks(chunk_t a, chunk_t b)
45: {
46: uint16_t sum;
47: uint8_t rem = 0;
48: ssize_t i, j;
49:
50: for (i = a.len - 1, j = b.len -1; i >= 0 && j >= 0; i--, j--)
51: {
52: sum = a.ptr[i] + b.ptr[j] + rem;
53: a.ptr[i] = (u_char)sum;
54: rem = sum >> 8;
55: }
56: for (; i >= 0 && rem; i--)
57: {
58: sum = a.ptr[i] + rem;
59: a.ptr[i] = (u_char)sum;
60: rem = sum >> 8;
61: }
62: }
63:
64: /**
65: * Do the actual key derivation with the given hasher, password and id.
66: */
67: static bool derive_key(hash_algorithm_t hash, chunk_t unicode, chunk_t salt,
68: uint64_t iterations, char id, chunk_t result)
69: {
70: chunk_t out = result, D, S, P = chunk_empty, I, Ai, B, Ij;
71: hasher_t *hasher;
72: size_t Slen, v, u;
73: uint64_t i;
74: bool success = FALSE;
75:
76: hasher = lib->crypto->create_hasher(lib->crypto, hash);
77: if (!hasher)
78: {
79: DBG1(DBG_ASN, " %N hash algorithm not available",
80: hash_algorithm_names, hash);
81: return FALSE;
82: }
83: switch (hash)
84: {
85: case HASH_MD2:
86: case HASH_MD5:
87: case HASH_SHA1:
88: case HASH_SHA224:
89: case HASH_SHA256:
90: v = 64;
91: break;
92: case HASH_SHA384:
93: case HASH_SHA512:
94: v = 128;
95: break;
96: default:
97: goto end;
98: }
99: u = hasher->get_hash_size(hasher);
100:
101: D = chunk_alloca(v);
102: memset(D.ptr, id, D.len);
103:
104: Slen = PKCS12_LEN(salt.len, v);
105: I = chunk_alloca(Slen + PKCS12_LEN(unicode.len, v));
106: S = chunk_create(I.ptr, Slen);
107: P = chunk_create(I.ptr + Slen, I.len - Slen);
108: copy_chunk(S, salt);
109: copy_chunk(P, unicode);
110:
111: Ai = chunk_alloca(u);
112: B = chunk_alloca(v);
113:
114: while (TRUE)
115: {
116: if (!hasher->get_hash(hasher, D, NULL) ||
117: !hasher->get_hash(hasher, I, Ai.ptr))
118: {
119: goto end;
120: }
121: for (i = 1; i < iterations; i++)
122: {
123: if (!hasher->get_hash(hasher, Ai, Ai.ptr))
124: {
125: goto end;
126: }
127: }
128: memcpy(out.ptr, Ai.ptr, min(out.len, Ai.len));
129: out = chunk_skip(out, Ai.len);
130: if (!out.len)
131: {
132: break;
133: }
134: copy_chunk(B, Ai);
135: /* B = B+1 */
136: add_chunks(B, chunk_from_chars(0x01));
137: Ij = chunk_create(I.ptr, v);
138: for (i = 0; i < I.len; i += v, Ij.ptr += v)
139: { /* Ij = Ij + B + 1 */
140: add_chunks(Ij, B);
141: }
142: }
143: success = TRUE;
144: end:
145: hasher->destroy(hasher);
146: return success;
147: }
148:
149: /*
150: * Described in header
151: */
152: bool pkcs12_derive_key(hash_algorithm_t hash, chunk_t password, chunk_t salt,
153: uint64_t iterations, pkcs12_key_type_t type, chunk_t key)
154: {
155: chunk_t unicode = chunk_empty;
156: bool success;
157: int i;
158:
159: if (password.len)
160: { /* convert the password to UTF-16BE (without BOM) with 0 terminator */
161: unicode = chunk_alloca(password.len * 2 + 2);
162: for (i = 0; i < password.len; i++)
163: {
164: unicode.ptr[i * 2] = 0;
165: unicode.ptr[i * 2 + 1] = password.ptr[i];
166: }
167: unicode.ptr[i * 2] = 0;
168: unicode.ptr[i * 2 + 1] = 0;
169: }
170:
171: success = derive_key(hash, unicode, salt, iterations, type, key);
172: memwipe(unicode.ptr, unicode.len);
173: return success;
174: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>