diff options
author | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2016-08-26 14:49:07 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2016-09-06 14:55:00 +0200 |
commit | a741b19ca3251caebeb3056662014c05433d291a (patch) | |
tree | 006de766f8d35b9398026fc53519d238bb28548c | |
parent | a80a0f727c705823239b043c82dec9bc41deef3d (diff) | |
download | gnutls-a741b19ca3251caebeb3056662014c05433d291a.tar.gz |
pkcs12: enhanced to allow encrypting using UCS2 passwords
That is use _gnutls_utf8_to_ucs2() to convert the provided
password to UCS2.
-rw-r--r-- | lib/x509/pkcs12_encr.c | 82 |
1 files changed, 42 insertions, 40 deletions
diff --git a/lib/x509/pkcs12_encr.c b/lib/x509/pkcs12_encr.c index 5c6de640db..0d4cb17386 100644 --- a/lib/x509/pkcs12_encr.c +++ b/lib/x509/pkcs12_encr.c @@ -27,23 +27,7 @@ #include <c-ctype.h> #include <algorithms.h> -/* Returns 0 if the password is ok, or a negative error - * code instead. - */ -static int _pkcs12_check_pass(const char *pass, size_t plen) -{ - unsigned int i; - - for (i = 0; i < plen; i++) { - if (c_isascii(pass[i])) - continue; - return GNUTLS_E_INVALID_PASSWORD; - } - - return 0; -} - -#define MAX_PASS_LEN 128 +#define MAX_PASS_LEN 256 /* ID should be: * 3 for MAC @@ -66,10 +50,11 @@ _gnutls_pkcs12_string_to_key(const mac_entry_st * me, bigint_t num_b1 = NULL, num_ij = NULL; bigint_t mpi512 = NULL; unsigned int pwlen; - uint8_t hash[MAX_HASH_SIZE], buf_b[64], buf_i[MAX_PASS_LEN * 2 + 64], *p; + uint8_t hash[MAX_HASH_SIZE], buf_b[64], buf_i[MAX_PASS_LEN + 64], *p; uint8_t d[64]; size_t cur_keylen; size_t n, m, p_size, i_size; + gnutls_datum_t ucs2 = {NULL, 0}; unsigned mac_len; const uint8_t buf_512[] = /* 2^64 */ { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -83,46 +68,65 @@ _gnutls_pkcs12_string_to_key(const mac_entry_st * me, cur_keylen = 0; - if (pw == NULL) - pwlen = 0; - else - pwlen = strlen(pw); - - if (pwlen > MAX_PASS_LEN) - return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); - if (me->block_size != 64) return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE); - if ((rc = _pkcs12_check_pass(pw, pwlen)) < 0) { - gnutls_assert(); - return rc; + if (pw) { + pwlen = strlen(pw); + + if (pwlen == 0) { + ucs2.data = gnutls_calloc(1, 2); + if (ucs2.data == NULL) + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + ucs2.size = 2; + } else { + rc = _gnutls_utf8_to_ucs2(pw, pwlen, &ucs2); + if (rc < 0) + return gnutls_assert_val(rc); + + /* include terminating zero */ + ucs2.size+=2; + } + pwlen = ucs2.size; + pw = (char*)ucs2.data; + } else { + pwlen = 0; + } + + if (pwlen > MAX_PASS_LEN) { + rc = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + goto cleanup; } rc = _gnutls_mpi_init_scan(&mpi512, buf_512, sizeof(buf_512)); if (rc < 0) { gnutls_assert(); - return rc; + goto cleanup; } /* Store salt and password in BUF_I */ p_size = ((pwlen / 64) * 64) + 64; - if (p_size > sizeof(buf_i) - 64) - return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + if (p_size > sizeof(buf_i) - 64) { + rc = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + goto cleanup; + } p = buf_i; for (i = 0; i < 64; i++) *p++ = salt[i % salt_size]; + if (pw) { for (i = j = 0; i < p_size; i += 2) { - *p++ = 0; *p++ = pw[j]; - if (++j > pwlen) /* Note, that we include the trailing (0) */ + *p++ = pw[j+1]; + j+=2; + if (j >= pwlen) j = 0; } - } else + } else { memset(p, 0, p_size); + } i_size = 64 + p_size; mac_len = _gnutls_mac_get_algo_len(me); @@ -167,7 +171,7 @@ _gnutls_pkcs12_string_to_key(const mac_entry_st * me, gnutls_assert(); goto cleanup; } - + for (i = 0; i < 128; i += 64) { n = 64; rc = _gnutls_mpi_init_scan(&num_ij, buf_i + i, n); @@ -183,11 +187,8 @@ _gnutls_pkcs12_string_to_key(const mac_entry_st * me, } n = 64; -#ifndef PKCS12_BROKEN_KEYGEN m = (_gnutls_mpi_get_nbits(num_ij) + 7) / 8; -#else - m = n; -#endif + memset(buf_i + i, 0, n - m); rc = _gnutls_mpi_print(num_ij, buf_i + i + n - m, &n); @@ -202,6 +203,7 @@ _gnutls_pkcs12_string_to_key(const mac_entry_st * me, _gnutls_mpi_release(&num_ij); _gnutls_mpi_release(&num_b1); _gnutls_mpi_release(&mpi512); + gnutls_free(ucs2.data); return rc; } |