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