corrected copyright notices
[gnutls.git] / lib / x509 / pkcs12_encr.c
blobba4e39e98cfe25f7a308dedd1cf3d050654e05be
1 /* minip12.c - A mini pkcs-12 implementation (modified for gnutls)
3 * Copyright (C) 2002-2012 Free Software Foundation, Inc.
5 * This file is part of GnuTLS.
7 * The GnuTLS is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public License
9 * as published by the Free Software Foundation; either version 3 of
10 * the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>
22 #include <gnutls_int.h>
24 #include <gnutls_mpi.h>
25 #include <gnutls_errors.h>
26 #include <x509_int.h>
28 /* Returns 0 if the password is ok, or a negative error
29 * code instead.
31 static int
32 _pkcs12_check_pass (const char *pass, size_t plen)
34 unsigned int i;
36 for (i = 0; i < plen; i++)
38 if (isascii (pass[i]))
39 continue;
40 return GNUTLS_E_INVALID_PASSWORD;
43 return 0;
46 #define MAX_PASS_LEN 128
48 /* ID should be:
49 * 3 for MAC
50 * 2 for IV
51 * 1 for encryption key
53 * Note that this function produces different key for the
54 * NULL password, and for the password with zero length.
56 int
57 _gnutls_pkcs12_string_to_key (unsigned int id, const uint8_t * salt,
58 unsigned int salt_size, unsigned int iter,
59 const char *pw, unsigned int req_keylen,
60 uint8_t * keybuf)
62 int rc;
63 unsigned int i, j;
64 digest_hd_st md;
65 bigint_t num_b1 = NULL, num_ij = NULL;
66 bigint_t mpi512 = NULL;
67 unsigned int pwlen;
68 uint8_t hash[20], buf_b[64], buf_i[MAX_PASS_LEN*2+64], *p;
69 uint8_t d[64];
70 size_t cur_keylen;
71 size_t n, m, p_size, i_size;
72 const uint8_t buf_512[] = /* 2^64 */
73 { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
74 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
75 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
77 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
78 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
79 0x00, 0x00, 0x00, 0x00, 0x00
82 cur_keylen = 0;
84 if (pw == NULL)
85 pwlen = 0;
86 else
87 pwlen = strlen (pw);
89 if (pwlen > MAX_PASS_LEN)
91 gnutls_assert ();
92 return GNUTLS_E_INVALID_REQUEST;
95 if ((rc = _pkcs12_check_pass (pw, pwlen)) < 0)
97 gnutls_assert ();
98 return rc;
101 rc = _gnutls_mpi_scan (&mpi512, buf_512, sizeof (buf_512));
102 if (rc < 0)
104 gnutls_assert ();
105 return rc;
108 /* Store salt and password in BUF_I */
109 p_size = ((pwlen/64)*64) + 64;
111 if (p_size > sizeof(buf_i)-64)
112 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
114 p = buf_i;
115 for (i = 0; i < 64; i++)
116 *p++ = salt[i % salt_size];
117 if (pw)
119 for (i = j = 0; i < p_size; i += 2)
121 *p++ = 0;
122 *p++ = pw[j];
123 if (++j > pwlen) /* Note, that we include the trailing (0) */
124 j = 0;
127 else
128 memset (p, 0, p_size);
130 i_size = 64+p_size;
132 for (;;)
134 rc = _gnutls_hash_init (&md, GNUTLS_MAC_SHA1);
135 if (rc < 0)
137 gnutls_assert ();
138 goto cleanup;
140 memset(d, id & 0xff, 64);
141 _gnutls_hash (&md, d, 64);
142 _gnutls_hash (&md, buf_i, pw ? i_size : 64);
143 _gnutls_hash_deinit (&md, hash);
144 for (i = 1; i < iter; i++)
146 rc = _gnutls_hash_fast (GNUTLS_MAC_SHA1, hash, 20, hash);
147 if (rc < 0)
149 gnutls_assert ();
150 goto cleanup;
153 for (i = 0; i < 20 && cur_keylen < req_keylen; i++)
154 keybuf[cur_keylen++] = hash[i];
155 if (cur_keylen == req_keylen)
157 rc = 0; /* ready */
158 goto cleanup;
161 /* need more bytes. */
162 for (i = 0; i < 64; i++)
163 buf_b[i] = hash[i % 20];
164 n = 64;
165 rc = _gnutls_mpi_scan (&num_b1, buf_b, n);
166 if (rc < 0)
168 gnutls_assert ();
169 goto cleanup;
171 _gnutls_mpi_add_ui (num_b1, num_b1, 1);
172 for (i = 0; i < 128; i += 64)
174 n = 64;
175 rc = _gnutls_mpi_scan (&num_ij, buf_i + i, n);
176 if (rc < 0)
178 gnutls_assert ();
179 goto cleanup;
181 _gnutls_mpi_addm (num_ij, num_ij, num_b1, mpi512);
182 n = 64;
183 #ifndef PKCS12_BROKEN_KEYGEN
184 m = (_gnutls_mpi_get_nbits (num_ij) + 7) / 8;
185 #else
186 m = n;
187 #endif
188 memset (buf_i + i, 0, n - m);
189 rc = _gnutls_mpi_print (num_ij, buf_i + i + n - m, &n);
190 if (rc < 0)
192 gnutls_assert ();
193 goto cleanup;
195 _gnutls_mpi_release (&num_ij);
198 cleanup:
199 _gnutls_mpi_release (&num_ij);
200 _gnutls_mpi_release (&num_b1);
201 _gnutls_mpi_release (&mpi512);
203 return rc;