* [including the GNU Public Licence.]
*/
/* ====================================================================
- * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
return(r);
}
-static BN_BLINDING *rsa_get_blinding(RSA *rsa, BIGNUM **r, int *local, BN_CTX *ctx)
+static BN_BLINDING *rsa_get_blinding(RSA *rsa, int *local, BN_CTX *ctx)
{
BN_BLINDING *ret;
+ int got_write_lock = 0;
+
+ CRYPTO_r_lock(CRYPTO_LOCK_RSA);
if (rsa->blinding == NULL)
{
+ CRYPTO_r_unlock(CRYPTO_LOCK_RSA);
+ CRYPTO_w_lock(CRYPTO_LOCK_RSA);
+ got_write_lock = 1;
+
if (rsa->blinding == NULL)
- {
- CRYPTO_w_lock(CRYPTO_LOCK_RSA);
- if (rsa->blinding == NULL)
- rsa->blinding = RSA_setup_blinding(rsa, ctx);
- CRYPTO_w_unlock(CRYPTO_LOCK_RSA);
- }
+ rsa->blinding = RSA_setup_blinding(rsa, ctx);
}
ret = rsa->blinding;
if (ret == NULL)
- return NULL;
+ goto err;
- if (BN_BLINDING_get_thread_id(ret) != CRYPTO_thread_id())
+ if (BN_BLINDING_get_thread_id(ret) == CRYPTO_thread_id())
+ {
+ /* rsa->blinding is ours! */
+
+ *local = 1;
+ }
+ else
{
- *local = 0;
+ /* resort to rsa->mt_blinding instead */
+
+ *local = 0; /* instructs rsa_blinding_convert(), rsa_blinding_invert()
+ * that the BN_BLINDING is shared, meaning that accesses
+ * require locks, and that the blinding factor must be
+ * stored outside the BN_BLINDING
+ */
+
if (rsa->mt_blinding == NULL)
{
- CRYPTO_w_lock(CRYPTO_LOCK_RSA);
+ if (!got_write_lock)
+ {
+ CRYPTO_r_unlock(CRYPTO_LOCK_RSA);
+ CRYPTO_w_lock(CRYPTO_LOCK_RSA);
+ got_write_lock = 1;
+ }
+
if (rsa->mt_blinding == NULL)
rsa->mt_blinding = RSA_setup_blinding(rsa, ctx);
- CRYPTO_w_unlock(CRYPTO_LOCK_RSA);
}
ret = rsa->mt_blinding;
}
- else
- *local = 1;
+ err:
+ if (got_write_lock)
+ CRYPTO_w_unlock(CRYPTO_LOCK_RSA);
+ else
+ CRYPTO_r_unlock(CRYPTO_LOCK_RSA);
return ret;
}
else
{
int ret;
- CRYPTO_w_lock(CRYPTO_LOCK_RSA_BLINDING);
+ CRYPTO_r_lock(CRYPTO_LOCK_RSA_BLINDING);
ret = BN_BLINDING_convert_ex(f, r, b, ctx);
- CRYPTO_w_unlock(CRYPTO_LOCK_RSA_BLINDING);
+ CRYPTO_r_unlock(CRYPTO_LOCK_RSA_BLINDING);
return ret;
}
}
else
{
int ret;
- CRYPTO_r_lock(CRYPTO_LOCK_RSA_BLINDING);
+ CRYPTO_w_lock(CRYPTO_LOCK_RSA_BLINDING);
ret = BN_BLINDING_invert_ex(f, r, b, ctx);
- CRYPTO_r_unlock(CRYPTO_LOCK_RSA_BLINDING);
+ CRYPTO_w_unlock(CRYPTO_LOCK_RSA_BLINDING);
return ret;
}
}
static int RSA_eay_private_encrypt(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding)
{
- BIGNUM *f, *ret, *br;
+ BIGNUM *f, *ret, *br, *res;
int i,j,k,num=0,r= -1;
unsigned char *buf=NULL;
BN_CTX *ctx=NULL;
case RSA_PKCS1_PADDING:
i=RSA_padding_add_PKCS1_type_1(buf,num,from,flen);
break;
+ case RSA_X931_PADDING:
+ i=RSA_padding_add_X931(buf,num,from,flen);
+ break;
case RSA_NO_PADDING:
i=RSA_padding_add_none(buf,num,from,flen);
break;
if (!(rsa->flags & RSA_FLAG_NO_BLINDING))
{
- blinding = rsa_get_blinding(rsa, &br, &local_blinding, ctx);
+ blinding = rsa_get_blinding(rsa, &local_blinding, ctx);
if (blinding == NULL)
{
RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR);
if (!rsa_blinding_invert(blinding, local_blinding, ret, br, ctx))
goto err;
+ if (padding == RSA_X931_PADDING)
+ {
+ BN_sub(f, rsa->n, ret);
+ if (BN_cmp(ret, f))
+ res = f;
+ else
+ res = ret;
+ }
+ else
+ res = ret;
+
/* put in leading 0 bytes if the number is less than the
* length of the modulus */
- j=BN_num_bytes(ret);
- i=BN_bn2bin(ret,&(to[num-j]));
+ j=BN_num_bytes(res);
+ i=BN_bn2bin(res,&(to[num-j]));
for (k=0; k<(num-i); k++)
to[k]=0;
if (!(rsa->flags & RSA_FLAG_NO_BLINDING))
{
- blinding = rsa_get_blinding(rsa, &br, &local_blinding, ctx);
+ blinding = rsa_get_blinding(rsa, &local_blinding, ctx);
if (blinding == NULL)
{
RSAerr(RSA_F_RSA_EAY_PRIVATE_DECRYPT, ERR_R_INTERNAL_ERROR);
if (!rsa->meth->bn_mod_exp(ret,f,rsa->e,rsa->n,ctx,
rsa->_method_mod_n)) goto err;
+ if ((padding == RSA_X931_PADDING) && ((ret->d[0] & 0xf) != 12))
+ BN_sub(ret, rsa->n, ret);
+
p=buf;
i=BN_bn2bin(ret,p);
{
case RSA_PKCS1_PADDING:
r=RSA_padding_check_PKCS1_type_1(to,num,buf,i,num);
+ /* Generally signatures should be at least 2/3 padding, though
+ this isn't possible for really short keys and some standard
+ signature schemes, so don't check if the unpadded data is
+ small. */
+ if(r > 42 && 3*8*r >= BN_num_bits(rsa->n))
+ {
+ RSAerr(RSA_F_RSA_EAY_PUBLIC_DECRYPT, RSA_R_PKCS1_PADDING_TOO_SHORT);
+ goto err;
+ }
+ break;
+ case RSA_X931_PADDING:
+ r=RSA_padding_check_X931(to,num,buf,i,num);
break;
case RSA_NO_PADDING:
r=RSA_padding_check_none(to,num,buf,i,num);