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>
28 /* Returns 0 if the password is ok, or a negative error
32 _pkcs12_check_pass (const char *pass
, size_t plen
)
36 for (i
= 0; i
< plen
; i
++)
38 if (isascii (pass
[i
]))
40 return GNUTLS_E_INVALID_PASSWORD
;
46 #define MAX_PASS_LEN 128
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.
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
,
65 bigint_t num_b1
= NULL
, num_ij
= NULL
;
66 bigint_t mpi512
= NULL
;
68 uint8_t hash
[20], buf_b
[64], buf_i
[MAX_PASS_LEN
*2+64], *p
;
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
89 if (pwlen
> MAX_PASS_LEN
)
92 return GNUTLS_E_INVALID_REQUEST
;
95 if ((rc
= _pkcs12_check_pass (pw
, pwlen
)) < 0)
101 rc
= _gnutls_mpi_scan (&mpi512
, buf_512
, sizeof (buf_512
));
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
);
115 for (i
= 0; i
< 64; i
++)
116 *p
++ = salt
[i
% salt_size
];
119 for (i
= j
= 0; i
< p_size
; i
+= 2)
123 if (++j
> pwlen
) /* Note, that we include the trailing (0) */
128 memset (p
, 0, p_size
);
134 rc
= _gnutls_hash_init (&md
, GNUTLS_MAC_SHA1
);
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
);
153 for (i
= 0; i
< 20 && cur_keylen
< req_keylen
; i
++)
154 keybuf
[cur_keylen
++] = hash
[i
];
155 if (cur_keylen
== req_keylen
)
161 /* need more bytes. */
162 for (i
= 0; i
< 64; i
++)
163 buf_b
[i
] = hash
[i
% 20];
165 rc
= _gnutls_mpi_scan (&num_b1
, buf_b
, n
);
171 _gnutls_mpi_add_ui (num_b1
, num_b1
, 1);
172 for (i
= 0; i
< 128; i
+= 64)
175 rc
= _gnutls_mpi_scan (&num_ij
, buf_i
+ i
, n
);
181 _gnutls_mpi_addm (num_ij
, num_ij
, num_b1
, mpi512
);
183 #ifndef PKCS12_BROKEN_KEYGEN
184 m
= (_gnutls_mpi_get_nbits (num_ij
) + 7) / 8;
188 memset (buf_i
+ i
, 0, n
- m
);
189 rc
= _gnutls_mpi_print (num_ij
, buf_i
+ i
+ n
- m
, &n
);
195 _gnutls_mpi_release (&num_ij
);
199 _gnutls_mpi_release (&num_ij
);
200 _gnutls_mpi_release (&num_b1
);
201 _gnutls_mpi_release (&mpi512
);