Line data Source code
1 : /*
2 : * Copyright (C) 2016 Red Hat
3 : *
4 : * Author: Nikos Mavrogiannopoulos
5 : *
6 : * This file is part of GnuTLS.
7 : *
8 : * The GnuTLS is free software; you can redistribute it and/or
9 : * modify it under the terms of the GNU Lesser General Public License
10 : * as published by the Free Software Foundation; either version 2.1 of
11 : * the License, or (at your option) any later version.
12 : *
13 : * This library is distributed in the hope that it will be useful, but
14 : * WITHOUT ANY WARRANTY; without even the implied warranty of
15 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 : * Lesser General Public License for more details.
17 : *
18 : * You should have received a copy of the GNU Lesser General Public License
19 : * along with this program. If not, see <https://www.gnu.org/licenses/>
20 : *
21 : */
22 :
23 : #include "gnutls_int.h"
24 :
25 : #include <datum.h>
26 : #include <global.h>
27 : #include "errors.h"
28 : #include <common.h>
29 : #include <x509.h>
30 : #include <x509_b64.h>
31 : #include "x509_int.h"
32 : #include "pkcs7_int.h"
33 : #include <algorithms.h>
34 : #include <nettle/md5.h>
35 :
36 : /* This file includes support for PKCS#8 PBES1 with DES and MD5.
37 : * We only support decryption for compatibility with other software.
38 : */
39 :
40 31 : int _gnutls_read_pbkdf1_params(const uint8_t * data, int data_size,
41 : struct pbkdf2_params *kdf_params,
42 : struct pbe_enc_params *enc_params)
43 : {
44 31 : ASN1_TYPE pasn = ASN1_TYPE_EMPTY;
45 31 : int len;
46 31 : int ret, result;
47 :
48 31 : memset(kdf_params, 0, sizeof(*kdf_params));
49 31 : memset(enc_params, 0, sizeof(*enc_params));
50 :
51 62 : if ((result =
52 31 : asn1_create_element(_gnutls_get_pkix(),
53 : "PKIX1.pkcs-5-PBE-params",
54 : &pasn)) != ASN1_SUCCESS) {
55 0 : gnutls_assert();
56 0 : return _gnutls_asn2err(result);
57 : }
58 :
59 : /* Decode the parameters.
60 : */
61 31 : result =
62 31 : _asn1_strict_der_decode(&pasn, data, data_size, NULL);
63 31 : if (result != ASN1_SUCCESS) {
64 2 : gnutls_assert();
65 2 : ret = _gnutls_asn2err(result);
66 2 : goto error;
67 : }
68 :
69 29 : ret =
70 29 : _gnutls_x509_read_uint(pasn, "iterationCount",
71 : &kdf_params->iter_count);
72 29 : if (ret < 0) {
73 2 : gnutls_assert();
74 2 : goto error;
75 : }
76 :
77 27 : if (kdf_params->iter_count >= MAX_ITER_COUNT || kdf_params->iter_count == 0) {
78 2 : ret = gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
79 2 : goto error;
80 : }
81 :
82 25 : len = sizeof(kdf_params->salt);
83 25 : result =
84 50 : asn1_read_value(pasn, "salt",
85 25 : kdf_params->salt, &len);
86 25 : if (result != ASN1_SUCCESS) {
87 0 : gnutls_assert();
88 0 : ret = _gnutls_asn2err(result);
89 0 : goto error;
90 : }
91 :
92 25 : if (len != 8) {
93 1 : gnutls_assert();
94 1 : ret = GNUTLS_E_ILLEGAL_PARAMETER;
95 1 : goto error;
96 : }
97 :
98 24 : enc_params->cipher = GNUTLS_CIPHER_DES_CBC;
99 :
100 24 : ret = 0;
101 31 : error:
102 31 : asn1_delete_structure2(&pasn, ASN1_DELETE_FLAG_ZEROIZE);
103 31 : return ret;
104 :
105 : }
106 :
107 20 : static void pbkdf1_md5(const char *password, unsigned password_len,
108 : const uint8_t salt[8], unsigned iter_count, unsigned key_size, uint8_t *key)
109 : {
110 20 : struct md5_ctx ctx;
111 20 : uint8_t tmp[16];
112 20 : unsigned i;
113 :
114 20 : if (key_size > sizeof(tmp))
115 0 : abort();
116 :
117 80324 : for (i=0;i<iter_count;i++) {
118 80304 : md5_init(&ctx);
119 80304 : if (i==0) {
120 20 : md5_update(&ctx, password_len, (uint8_t*)password);
121 20 : md5_update(&ctx, 8, salt);
122 20 : md5_digest(&ctx, 16, tmp);
123 : } else {
124 80284 : md5_update(&ctx, 16, tmp);
125 80284 : md5_digest(&ctx, 16, tmp);
126 : }
127 : }
128 :
129 20 : memcpy(key, tmp, key_size);
130 20 : return;
131 : }
132 :
133 : int
134 22 : _gnutls_decrypt_pbes1_des_md5_data(const char *password,
135 : unsigned password_len,
136 : const struct pbkdf2_params *kdf_params,
137 : const struct pbe_enc_params *enc_params,
138 : const gnutls_datum_t *encrypted_data,
139 : gnutls_datum_t *decrypted_data)
140 : {
141 22 : int result;
142 22 : gnutls_datum_t dkey, d_iv;
143 22 : cipher_hd_st ch;
144 22 : uint8_t key[16];
145 22 : const unsigned block_size = 8;
146 :
147 22 : if (enc_params->cipher != GNUTLS_CIPHER_DES_CBC)
148 0 : return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
149 :
150 22 : if (encrypted_data->size % block_size != 0)
151 2 : return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
152 :
153 : /* generate the key
154 : */
155 20 : pbkdf1_md5(password, password_len, kdf_params->salt, kdf_params->iter_count, sizeof(key), key);
156 :
157 20 : dkey.data = key;
158 20 : dkey.size = 8;
159 20 : d_iv.data = &key[8];
160 20 : d_iv.size = 8;
161 20 : result =
162 20 : _gnutls_cipher_init(&ch, cipher_to_entry(GNUTLS_CIPHER_DES_CBC),
163 : &dkey, &d_iv, 0);
164 20 : if (result < 0)
165 0 : return gnutls_assert_val(result);
166 :
167 20 : result = _gnutls_cipher_decrypt(&ch, encrypted_data->data, encrypted_data->size);
168 20 : if (result < 0) {
169 0 : gnutls_assert();
170 0 : goto error;
171 : }
172 :
173 20 : if ((int)encrypted_data->size - encrypted_data->data[encrypted_data->size - 1] < 0) {
174 1 : gnutls_assert();
175 1 : result = GNUTLS_E_ILLEGAL_PARAMETER;
176 1 : goto error;
177 : }
178 :
179 19 : decrypted_data->data = encrypted_data->data;
180 19 : decrypted_data->size = encrypted_data->size - encrypted_data->data[encrypted_data->size - 1];
181 :
182 19 : result = 0;
183 20 : error:
184 20 : _gnutls_cipher_deinit(&ch);
185 :
186 : return result;
187 : }
188 :
|