I've got a project ( https://github.com/zackw/moeller-ref ) which does
a bunch of elliptic curve operations against custom curves, using the
OpenSSL and/or Crypto++ low-level APIs (two parallel implementations
of the same asymmetric cryptosystem).  One function in each
implementation performs decryption and therefore needs to run in
constant time to prevent timing attacks.  But nearly all the functions
in <openssl/ec.h> and <openssl/bn.h> can fail, which means there are a
good *nine* early exits from the decryption routine, all of them
potentially data-dependent.

I'm appending the problematic routine.  Does anyone know how to revise
it so that even under failure conditions it always takes the same
amount of time?  You can see the whole file at
https://github.com/zackw/moeller-ref/blob/master/mref-o.c .

(The Crypto++ implementation probably has the same problem, but it's
so slow that I do not imagine its being used for reals, and in any
case, the immediate use I have for this code is in an application
based on OpenSSL.)

Thanks,
zw

int
MKEM_decode_message(const MKEM *kp, uint8_t *secret, const uint8_t *message)
{
 int use_curve0 = !(message[0] & kp->params->curve_bit);
 const EC_GROUP *ca = use_curve0 ? kp->params->c0 : kp->params->c1;
 const BIGNUM *sa = use_curve0 ? kp->s0 : kp->s1;
 EC_POINT *q = 0, *r = 0;
 uint8_t *unpadded = 0;
 BIGNUM x, y;
 size_t mlen = kp->params->msgsize;
 int rv;

 if (!kp->s0 || !kp->s1) /* secret key not available */
   return -1;

 BN_init(&x);
 BN_init(&y);
 FAILZ(q = EC_POINT_new(ca));
 FAILZ(r = EC_POINT_new(ca));
 FAILZ(unpadded = malloc(mlen + 1));

 /* Copy the message, erase the padding bits, and put an 0x02 byte on
    the front so we can use EC_POINT_oct2point to recover the
    y-coordinate. */
 unpadded[0] = 0x02;
 unpadded[1] = (message[0] & ~(kp->params->pad_mask|kp->params->curve_bit));
 memcpy(&unpadded[2], &message[1], mlen - 1);

 FAILZ(EC_POINT_oct2point(ca, q, unpadded, mlen + 1,
                          kp->params->ctx));
 FAILZ(EC_POINT_mul(ca, r, 0, q, sa, kp->params->ctx));

 FAILZ(EC_POINT_get_affine_coordinates_GF2m(ca, q, &x, &y, kp->params->ctx));
 if (bn2bin_padhi(&x, secret, mlen) != mlen)
   goto fail;

 FAILZ(EC_POINT_get_affine_coordinates_GF2m(ca, r, &x, &y, kp->params->ctx));
 if (bn2bin_padhi(&x, secret + mlen, mlen) != mlen)
   goto fail;

 rv = 0;
 done:
 if (unpadded) {
   memset(unpadded, 0, mlen + 1);
   free(unpadded);
 }
 if (q) EC_POINT_clear_free(q);
 if (r) EC_POINT_clear_free(r);
 BN_clear(&x);
 BN_clear(&y);
 return rv;

 fail:
 rv = -1;
 memset(secret, 0, mlen * 2);
 goto done;
}
______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    openssl-users@openssl.org
Automated List Manager                           majord...@openssl.org

Reply via email to