|
Packit |
aea12f |
/*
|
|
Packit |
aea12f |
* Copyright (C) 2016 Red Hat
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* Author: Nikos Mavrogiannopoulos
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* This file is part of GnuTLS.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* The GnuTLS is free software; you can redistribute it and/or
|
|
Packit |
aea12f |
* modify it under the terms of the GNU Lesser General Public License
|
|
Packit |
aea12f |
* as published by the Free Software Foundation; either version 2.1 of
|
|
Packit |
aea12f |
* the License, or (at your option) any later version.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* This library is distributed in the hope that it will be useful, but
|
|
Packit |
aea12f |
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
aea12f |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
aea12f |
* Lesser General Public License for more details.
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
* You should have received a copy of the GNU Lesser General Public License
|
|
Packit |
aea12f |
* along with this program. If not, see <https://www.gnu.org/licenses/>
|
|
Packit |
aea12f |
*
|
|
Packit |
aea12f |
*/
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
#include "gnutls_int.h"
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
#include <datum.h>
|
|
Packit |
aea12f |
#include <global.h>
|
|
Packit |
aea12f |
#include "errors.h"
|
|
Packit |
aea12f |
#include <common.h>
|
|
Packit |
aea12f |
#include <x509.h>
|
|
Packit |
aea12f |
#include <x509_b64.h>
|
|
Packit |
aea12f |
#include "x509_int.h"
|
|
Packit |
aea12f |
#include "pkcs7_int.h"
|
|
Packit |
aea12f |
#include <algorithms.h>
|
|
Packit |
aea12f |
#include <nettle/md5.h>
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* This file includes support for PKCS#8 PBES1 with DES and MD5.
|
|
Packit |
aea12f |
* We only support decryption for compatibility with other software.
|
|
Packit |
aea12f |
*/
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
int _gnutls_read_pbkdf1_params(const uint8_t * data, int data_size,
|
|
Packit |
aea12f |
struct pbkdf2_params *kdf_params,
|
|
Packit |
aea12f |
struct pbe_enc_params *enc_params)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
ASN1_TYPE pasn = ASN1_TYPE_EMPTY;
|
|
Packit |
aea12f |
int len;
|
|
Packit |
aea12f |
int ret, result;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
memset(kdf_params, 0, sizeof(*kdf_params));
|
|
Packit |
aea12f |
memset(enc_params, 0, sizeof(*enc_params));
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if ((result =
|
|
Packit |
aea12f |
asn1_create_element(_gnutls_get_pkix(),
|
|
Packit |
aea12f |
"PKIX1.pkcs-5-PBE-params",
|
|
Packit |
aea12f |
&pasn)) != ASN1_SUCCESS) {
|
|
Packit |
aea12f |
gnutls_assert();
|
|
Packit |
aea12f |
return _gnutls_asn2err(result);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* Decode the parameters.
|
|
Packit |
aea12f |
*/
|
|
Packit |
aea12f |
result =
|
|
Packit |
aea12f |
_asn1_strict_der_decode(&pasn, data, data_size, NULL);
|
|
Packit |
aea12f |
if (result != ASN1_SUCCESS) {
|
|
Packit |
aea12f |
gnutls_assert();
|
|
Packit |
aea12f |
ret = _gnutls_asn2err(result);
|
|
Packit |
aea12f |
goto error;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret =
|
|
Packit |
aea12f |
_gnutls_x509_read_uint(pasn, "iterationCount",
|
|
Packit |
aea12f |
&kdf_params->iter_count);
|
|
Packit |
aea12f |
if (ret < 0) {
|
|
Packit |
aea12f |
gnutls_assert();
|
|
Packit |
aea12f |
goto error;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (kdf_params->iter_count >= MAX_ITER_COUNT || kdf_params->iter_count == 0) {
|
|
Packit |
aea12f |
ret = gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
|
|
Packit |
aea12f |
goto error;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
len = sizeof(kdf_params->salt);
|
|
Packit |
aea12f |
result =
|
|
Packit |
aea12f |
asn1_read_value(pasn, "salt",
|
|
Packit |
aea12f |
kdf_params->salt, &len;;
|
|
Packit |
aea12f |
if (result != ASN1_SUCCESS) {
|
|
Packit |
aea12f |
gnutls_assert();
|
|
Packit |
aea12f |
ret = _gnutls_asn2err(result);
|
|
Packit |
aea12f |
goto error;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (len != 8) {
|
|
Packit |
aea12f |
gnutls_assert();
|
|
Packit |
aea12f |
ret = GNUTLS_E_ILLEGAL_PARAMETER;
|
|
Packit |
aea12f |
goto error;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
enc_params->cipher = GNUTLS_CIPHER_DES_CBC;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ret = 0;
|
|
Packit |
aea12f |
error:
|
|
Packit |
aea12f |
asn1_delete_structure2(&pasn, ASN1_DELETE_FLAG_ZEROIZE);
|
|
Packit |
aea12f |
return ret;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
static void pbkdf1_md5(const char *password, unsigned password_len,
|
|
Packit |
aea12f |
const uint8_t salt[8], unsigned iter_count, unsigned key_size, uint8_t *key)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
struct md5_ctx ctx;
|
|
Packit |
aea12f |
uint8_t tmp[16];
|
|
Packit |
aea12f |
unsigned i;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (key_size > sizeof(tmp))
|
|
Packit |
aea12f |
abort();
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
for (i=0;i
|
|
Packit |
aea12f |
md5_init(&ctx;;
|
|
Packit |
aea12f |
if (i==0) {
|
|
Packit |
aea12f |
md5_update(&ctx, password_len, (uint8_t*)password);
|
|
Packit |
aea12f |
md5_update(&ctx, 8, salt);
|
|
Packit |
aea12f |
md5_digest(&ctx, 16, tmp);
|
|
Packit |
aea12f |
} else {
|
|
Packit |
aea12f |
md5_update(&ctx, 16, tmp);
|
|
Packit |
aea12f |
md5_digest(&ctx, 16, tmp);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
memcpy(key, tmp, key_size);
|
|
Packit |
aea12f |
return;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
int
|
|
Packit |
aea12f |
_gnutls_decrypt_pbes1_des_md5_data(const char *password,
|
|
Packit |
aea12f |
unsigned password_len,
|
|
Packit |
aea12f |
const struct pbkdf2_params *kdf_params,
|
|
Packit |
aea12f |
const struct pbe_enc_params *enc_params,
|
|
Packit Service |
991b93 |
const gnutls_datum_t *encrypted_data,
|
|
Packit |
aea12f |
gnutls_datum_t *decrypted_data)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
int result;
|
|
Packit |
aea12f |
gnutls_datum_t dkey, d_iv;
|
|
Packit |
aea12f |
cipher_hd_st ch;
|
|
Packit |
aea12f |
uint8_t key[16];
|
|
Packit |
aea12f |
const unsigned block_size = 8;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (enc_params->cipher != GNUTLS_CIPHER_DES_CBC)
|
|
Packit |
aea12f |
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (encrypted_data->size % block_size != 0)
|
|
Packit |
aea12f |
return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* generate the key
|
|
Packit |
aea12f |
*/
|
|
Packit |
aea12f |
pbkdf1_md5(password, password_len, kdf_params->salt, kdf_params->iter_count, sizeof(key), key);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
dkey.data = key;
|
|
Packit |
aea12f |
dkey.size = 8;
|
|
Packit |
aea12f |
d_iv.data = &key[8];
|
|
Packit |
aea12f |
d_iv.size = 8;
|
|
Packit |
aea12f |
result =
|
|
Packit |
aea12f |
_gnutls_cipher_init(&ch, cipher_to_entry(GNUTLS_CIPHER_DES_CBC),
|
|
Packit |
aea12f |
&dkey, &d_iv, 0);
|
|
Packit |
aea12f |
if (result < 0)
|
|
Packit |
aea12f |
return gnutls_assert_val(result);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
result = _gnutls_cipher_decrypt(&ch, encrypted_data->data, encrypted_data->size);
|
|
Packit |
aea12f |
if (result < 0) {
|
|
Packit |
aea12f |
gnutls_assert();
|
|
Packit |
aea12f |
goto error;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if ((int)encrypted_data->size - encrypted_data->data[encrypted_data->size - 1] < 0) {
|
|
Packit |
aea12f |
gnutls_assert();
|
|
Packit |
aea12f |
result = GNUTLS_E_ILLEGAL_PARAMETER;
|
|
Packit |
aea12f |
goto error;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
decrypted_data->data = encrypted_data->data;
|
|
Packit |
aea12f |
decrypted_data->size = encrypted_data->size - encrypted_data->data[encrypted_data->size - 1];
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
result = 0;
|
|
Packit |
aea12f |
error:
|
|
Packit |
aea12f |
_gnutls_cipher_deinit(&ch);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
return result;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|