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
_gnutls_read_pbkdf1_params(const uint8_t * data,int data_size,struct pbkdf2_params * kdf_params,struct pbe_enc_params * enc_params)40 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 ASN1_TYPE pasn = ASN1_TYPE_EMPTY;
45 int len;
46 int ret, result;
47
48 memset(kdf_params, 0, sizeof(*kdf_params));
49 memset(enc_params, 0, sizeof(*enc_params));
50
51 if ((result =
52 asn1_create_element(_gnutls_get_pkix(),
53 "PKIX1.pkcs-5-PBE-params",
54 &pasn)) != ASN1_SUCCESS) {
55 gnutls_assert();
56 return _gnutls_asn2err(result);
57 }
58
59 /* Decode the parameters.
60 */
61 result =
62 _asn1_strict_der_decode(&pasn, data, data_size, NULL);
63 if (result != ASN1_SUCCESS) {
64 gnutls_assert();
65 ret = _gnutls_asn2err(result);
66 goto error;
67 }
68
69 ret =
70 _gnutls_x509_read_uint(pasn, "iterationCount",
71 &kdf_params->iter_count);
72 if (ret < 0) {
73 gnutls_assert();
74 goto error;
75 }
76
77 if (kdf_params->iter_count >= MAX_ITER_COUNT || kdf_params->iter_count == 0) {
78 ret = gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
79 goto error;
80 }
81
82 len = sizeof(kdf_params->salt);
83 result =
84 asn1_read_value(pasn, "salt",
85 kdf_params->salt, &len);
86 if (result != ASN1_SUCCESS) {
87 gnutls_assert();
88 ret = _gnutls_asn2err(result);
89 goto error;
90 }
91
92 if (len != 8) {
93 gnutls_assert();
94 ret = GNUTLS_E_ILLEGAL_PARAMETER;
95 goto error;
96 }
97
98 enc_params->cipher = GNUTLS_CIPHER_DES_CBC;
99
100 ret = 0;
101 error:
102 asn1_delete_structure2(&pasn, ASN1_DELETE_FLAG_ZEROIZE);
103 return ret;
104
105 }
106
pbkdf1_md5(const char * password,unsigned password_len,const uint8_t salt[8],unsigned iter_count,unsigned key_size,uint8_t * key)107 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 struct md5_ctx ctx;
111 uint8_t tmp[16];
112 unsigned i;
113
114 if (key_size > sizeof(tmp))
115 abort();
116
117 for (i=0;i<iter_count;i++) {
118 md5_init(&ctx);
119 if (i==0) {
120 md5_update(&ctx, password_len, (uint8_t*)password);
121 md5_update(&ctx, 8, salt);
122 md5_digest(&ctx, 16, tmp);
123 } else {
124 md5_update(&ctx, 16, tmp);
125 md5_digest(&ctx, 16, tmp);
126 }
127 }
128
129 memcpy(key, tmp, key_size);
130 return;
131 }
132
133 int
_gnutls_decrypt_pbes1_des_md5_data(const char * password,unsigned password_len,const struct pbkdf2_params * kdf_params,const struct pbe_enc_params * enc_params,const gnutls_datum_t * encrypted_data,gnutls_datum_t * decrypted_data)134 _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 int result;
142 gnutls_datum_t dkey, d_iv;
143 cipher_hd_st ch;
144 uint8_t key[16];
145 const unsigned block_size = 8;
146
147 if (enc_params->cipher != GNUTLS_CIPHER_DES_CBC)
148 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
149
150 if (encrypted_data->size % block_size != 0)
151 return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
152
153 /* generate the key
154 */
155 pbkdf1_md5(password, password_len, kdf_params->salt, kdf_params->iter_count, sizeof(key), key);
156
157 dkey.data = key;
158 dkey.size = 8;
159 d_iv.data = &key[8];
160 d_iv.size = 8;
161 result =
162 _gnutls_cipher_init(&ch, cipher_to_entry(GNUTLS_CIPHER_DES_CBC),
163 &dkey, &d_iv, 0);
164 if (result < 0)
165 return gnutls_assert_val(result);
166
167 result = _gnutls_cipher_decrypt(&ch, encrypted_data->data, encrypted_data->size);
168 if (result < 0) {
169 gnutls_assert();
170 goto error;
171 }
172
173 if ((int)encrypted_data->size - encrypted_data->data[encrypted_data->size - 1] < 0) {
174 gnutls_assert();
175 result = GNUTLS_E_ILLEGAL_PARAMETER;
176 goto error;
177 }
178
179 decrypted_data->data = encrypted_data->data;
180 decrypted_data->size = encrypted_data->size - encrypted_data->data[encrypted_data->size - 1];
181
182 result = 0;
183 error:
184 _gnutls_cipher_deinit(&ch);
185
186 return result;
187 }
188
189