gcrypt: Support RSA OAEP SHA1 encryption/decryption
This commit is contained in:
@@ -135,6 +135,7 @@ METHOD(plugin_t, get_features, int,
|
|||||||
PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_SHA1),
|
PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_SHA1),
|
||||||
PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_MD5),
|
PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_MD5),
|
||||||
PLUGIN_PROVIDE(PRIVKEY_DECRYPT, ENCRYPT_RSA_PKCS1),
|
PLUGIN_PROVIDE(PRIVKEY_DECRYPT, ENCRYPT_RSA_PKCS1),
|
||||||
|
PLUGIN_PROVIDE(PRIVKEY_DECRYPT, ENCRYPT_RSA_OAEP_SHA1),
|
||||||
/* signature verification schemes */
|
/* signature verification schemes */
|
||||||
#if GCRYPT_VERSION_NUMBER >= 0x010700
|
#if GCRYPT_VERSION_NUMBER >= 0x010700
|
||||||
PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PSS),
|
PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PSS),
|
||||||
@@ -147,6 +148,7 @@ METHOD(plugin_t, get_features, int,
|
|||||||
PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_SHA1),
|
PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_SHA1),
|
||||||
PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_MD5),
|
PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_MD5),
|
||||||
PLUGIN_PROVIDE(PUBKEY_ENCRYPT, ENCRYPT_RSA_PKCS1),
|
PLUGIN_PROVIDE(PUBKEY_ENCRYPT, ENCRYPT_RSA_PKCS1),
|
||||||
|
PLUGIN_PROVIDE(PUBKEY_ENCRYPT, ENCRYPT_RSA_OAEP_SHA1),
|
||||||
/* random numbers */
|
/* random numbers */
|
||||||
PLUGIN_REGISTER(RNG, gcrypt_rng_create),
|
PLUGIN_REGISTER(RNG, gcrypt_rng_create),
|
||||||
PLUGIN_PROVIDE(RNG, RNG_WEAK),
|
PLUGIN_PROVIDE(RNG, RNG_WEAK),
|
||||||
|
|||||||
@@ -282,49 +282,53 @@ METHOD(private_key_t, decrypt, bool,
|
|||||||
{
|
{
|
||||||
gcry_error_t err;
|
gcry_error_t err;
|
||||||
gcry_sexp_t in, out;
|
gcry_sexp_t in, out;
|
||||||
chunk_t padded;
|
chunk_t label = chunk_empty, decrypted;
|
||||||
u_char *pos = NULL;;
|
u_char *sexp;
|
||||||
|
|
||||||
if (scheme != ENCRYPT_RSA_PKCS1)
|
switch (scheme)
|
||||||
{
|
{
|
||||||
DBG1(DBG_LIB, "encryption scheme %N not supported",
|
case ENCRYPT_RSA_PKCS1:
|
||||||
encryption_scheme_names, scheme);
|
sexp = "(enc-val(flags pkcs1)(rsa(a %b)))";
|
||||||
return FALSE;
|
break;
|
||||||
|
case ENCRYPT_RSA_OAEP_SHA1:
|
||||||
|
sexp = "(enc-val(flags oaep)(rsa(a %b)))";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
DBG1(DBG_LIB, "encryption scheme %N not supported",
|
||||||
|
encryption_scheme_names, scheme);
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
err = gcry_sexp_build(&in, NULL, "(enc-val(flags)(rsa(a %b)))",
|
|
||||||
encrypted.len, encrypted.ptr);
|
if (scheme == ENCRYPT_RSA_OAEP_SHA1 && params != NULL)
|
||||||
|
{
|
||||||
|
label = *(chunk_t *)params;
|
||||||
|
if (label.len > 0)
|
||||||
|
{
|
||||||
|
DBG1(DBG_LIB, "RSA OAEP decryption with a label not supported");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = gcry_sexp_build(&in, NULL, sexp, encrypted.len, encrypted.ptr);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
DBG1(DBG_LIB, "building decryption S-expression failed: %s",
|
DBG1(DBG_LIB, "building decryption S-expression failed: %s",
|
||||||
gpg_strerror(err));
|
gpg_strerror(err));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = gcry_pk_decrypt(&out, in, this->key);
|
err = gcry_pk_decrypt(&out, in, this->key);
|
||||||
gcry_sexp_release(in);
|
gcry_sexp_release(in);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
DBG1(DBG_LIB, "decrypting pkcs1 data failed: %s", gpg_strerror(err));
|
DBG1(DBG_LIB, "RSA decryption failed: %s", gpg_strerror(err));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
padded.ptr = (u_char*)gcry_sexp_nth_data(out, 1, &padded.len);
|
|
||||||
/* result is padded, but gcrypt strips leading zero:
|
decrypted.ptr = (u_char*)gcry_sexp_nth_data(out, 1, &decrypted.len);
|
||||||
* 00 | 02 | RANDOM | 00 | DATA */
|
*plain = chunk_clone(decrypted);
|
||||||
if (padded.ptr && padded.len > 2 && padded.ptr[0] == 0x02)
|
|
||||||
{
|
|
||||||
pos = memchr(padded.ptr, 0x00, padded.len - 1);
|
|
||||||
if (pos)
|
|
||||||
{
|
|
||||||
pos++;
|
|
||||||
*plain = chunk_clone(chunk_create(
|
|
||||||
pos, padded.len - (pos - padded.ptr)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
gcry_sexp_release(out);
|
gcry_sexp_release(out);
|
||||||
if (!pos)
|
|
||||||
{
|
|
||||||
DBG1(DBG_LIB, "decrypted data has invalid pkcs1 padding");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -239,36 +239,55 @@ METHOD(public_key_t, encrypt_, bool,
|
|||||||
private_gcrypt_rsa_public_key_t *this, encryption_scheme_t scheme,
|
private_gcrypt_rsa_public_key_t *this, encryption_scheme_t scheme,
|
||||||
void *params, chunk_t plain, chunk_t *encrypted)
|
void *params, chunk_t plain, chunk_t *encrypted)
|
||||||
{
|
{
|
||||||
gcry_sexp_t in, out;
|
|
||||||
gcry_error_t err;
|
gcry_error_t err;
|
||||||
|
gcry_sexp_t in, out;
|
||||||
|
chunk_t label = chunk_empty;
|
||||||
|
u_char *sexp;
|
||||||
|
|
||||||
if (scheme != ENCRYPT_RSA_PKCS1)
|
switch (scheme)
|
||||||
{
|
{
|
||||||
DBG1(DBG_LIB, "encryption scheme %N not supported",
|
case ENCRYPT_RSA_PKCS1:
|
||||||
encryption_scheme_names, scheme);
|
sexp = "(data(flags pkcs1)(value %b))";
|
||||||
return FALSE;
|
break;
|
||||||
|
case ENCRYPT_RSA_OAEP_SHA1:
|
||||||
|
sexp = "(data(flags oaep)(value %b))";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
DBG1(DBG_LIB, "encryption scheme %N not supported",
|
||||||
|
encryption_scheme_names, scheme);
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
/* "pkcs1" uses PKCS 1.5 (section 8.1) block type 2 encryption:
|
|
||||||
* 00 | 02 | RANDOM | 00 | DATA */
|
if (scheme == ENCRYPT_RSA_OAEP_SHA1 && params != NULL)
|
||||||
err = gcry_sexp_build(&in, NULL, "(data(flags pkcs1)(value %b))",
|
{
|
||||||
plain.len, plain.ptr);
|
label = *(chunk_t *)params;
|
||||||
|
if (label.len > 0)
|
||||||
|
{
|
||||||
|
DBG1(DBG_LIB, "RSA OAEP encryption with a label not supported");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = gcry_sexp_build(&in, NULL, sexp, plain.len, plain.ptr);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
DBG1(DBG_LIB, "building encryption S-expression failed: %s",
|
DBG1(DBG_LIB, "building encryption S-expression failed: %s",
|
||||||
gpg_strerror(err));
|
gpg_strerror(err));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = gcry_pk_encrypt(&out, in, this->key);
|
err = gcry_pk_encrypt(&out, in, this->key);
|
||||||
gcry_sexp_release(in);
|
gcry_sexp_release(in);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
DBG1(DBG_LIB, "encrypting data using pkcs1 failed: %s",
|
DBG1(DBG_LIB, "RSA encryption failed: %s", gpg_strerror(err));
|
||||||
gpg_strerror(err));
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
*encrypted = gcrypt_rsa_find_token(out, "a", this->key);
|
*encrypted = gcrypt_rsa_find_token(out, "a", this->key);
|
||||||
gcry_sexp_release(out);
|
gcry_sexp_release(out);
|
||||||
return !!encrypted->len;
|
|
||||||
|
return encrypted->len > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(public_key_t, get_keysize, int,
|
METHOD(public_key_t, get_keysize, int,
|
||||||
|
|||||||
Reference in New Issue
Block a user