34 RCSID(
"$Id: 1707ab5ae560ae86e0d31cad937ea17b5c121737 $")
37 #include <freeradius-devel/server/base.h>
38 #include <freeradius-devel/tls/base.h>
39 #include <freeradius-devel/server/module_rlm.h>
49 size_t mdlen = SHA256_DIGEST_LENGTH;
51 EVP_DigestSignFinal(hmac_ctx, digest, &mdlen);
52 EVP_MD_CTX_reset(hmac_ctx);
57 int label_len,
uint8_t *result,
int result_bit_len)
61 uint8_t digest[SHA256_DIGEST_LENGTH];
63 int result_byte_len, len = 0;
64 size_t mdlen = SHA256_DIGEST_LENGTH;
67 result_byte_len = (result_bit_len + 7) / 8;
70 L = htons(result_bit_len);
72 MEM(hmac_ctx = EVP_MD_CTX_new());
73 MEM(hmac_pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, key, keylen));
74 while (len < result_byte_len) {
75 ctr++; i = htons(ctr);
77 EVP_DigestSignInit(hmac_ctx, NULL, EVP_sha256(), NULL, hmac_pkey);
78 if (ctr > 1) EVP_DigestSignUpdate(hmac_ctx, digest, mdlen);
80 EVP_DigestSignUpdate(hmac_ctx, (
uint8_t const *)label, label_len);
82 EVP_DigestSignFinal(hmac_ctx, digest, &mdlen);
83 if ((len + (
int) mdlen) > result_byte_len) {
84 memcpy(result + len, digest, result_byte_len - len);
86 memcpy(result + len, digest, mdlen);
89 EVP_MD_CTX_reset(hmac_ctx);
93 if (result_bit_len % 8) {
94 mask <<= (8 - (result_bit_len % 8));
95 result[result_byte_len - 1] &=
mask;
98 EVP_MD_CTX_free(hmac_ctx);
99 EVP_PKEY_free(hmac_pkey);
107 if (bn) BN_set_flags(bn, BN_FLG_CONSTTIME);
114 static int legendre(BIGNUM *a, BIGNUM *p, BN_CTX *bnctx)
118 BIGNUM *res, *pm1over2;
123 if (!BN_sub(pm1over2, p, BN_value_one()) ||
124 !BN_rshift1(pm1over2, pm1over2) ||
125 !BN_mod_exp_mont_consttime(res, a, pm1over2, p, bnctx, NULL)) {
143 static void do_equation(EC_GROUP *group, BIGNUM *y2, BIGNUM *x, BN_CTX *bnctx)
145 BIGNUM *p, *a, *b, *tmp1, *pm1;
152 EC_GROUP_get_curve(group, p, a, b, bnctx);
154 BN_sub(pm1, p, BN_value_one());
159 BN_mod_sqr(tmp1, x, p, bnctx);
160 BN_mod_mul(y2, tmp1, x, p, bnctx);
161 BN_mod_mul(tmp1, a, x, p, bnctx);
162 BN_mod_add_quick(y2, y2, tmp1, p);
163 BN_mod_add_quick(y2, y2, b, p);
176 int offset,
check, ret = 0;
177 BIGNUM *r = NULL, *pm1 = NULL, *res = NULL, *qr_or_qnr = NULL;
179 unsigned char *qr_bin = NULL, *qnr_bin = NULL, *qr_or_qnr_bin = NULL;
189 if (((qr_bin = (
unsigned char *)malloc(BN_num_bytes(p))) == NULL) ||
190 ((qnr_bin = (
unsigned char *)malloc(BN_num_bytes(p))) == NULL) ||
191 ((qr_or_qnr_bin = (
unsigned char *)malloc(BN_num_bytes(p))) == NULL)) {
199 memset(qr_bin, 0, BN_num_bytes(p));
200 memset(qnr_bin, 0, BN_num_bytes(p));
201 memset(qr_or_qnr_bin, 0, BN_num_bytes(p));
203 offset = BN_num_bytes(p) - BN_num_bytes(qr);
204 BN_bn2bin(qr, qr_bin + offset);
206 offset = BN_num_bytes(p) - BN_num_bytes(qnr);
207 BN_bn2bin(qnr, qnr_bin + offset);
212 BN_sub(pm1, p, BN_value_one());
213 BN_rand_range(r, pm1);
214 BN_add(r, r, BN_value_one());
221 BN_mod_mul(res, res, r, p, bnctx);
222 BN_mod_mul(res, res, r, p, bnctx);
230 BN_bin2bn(qr_or_qnr_bin, BN_num_bytes(p), qr_or_qnr);
231 BN_mod_mul(res, res, qr_or_qnr, p, bnctx);
234 if ((ret =
legendre(res, p, bnctx)) == -2) {
242 if (qr_bin != NULL)
free(qr_bin);
243 if (qnr_bin != NULL)
free(qnr_bin);
244 if (qr_or_qnr_bin != NULL)
free(qr_or_qnr_bin);
254 char const *password,
int password_len,
255 char const *id_server,
int id_server_len,
256 char const *id_peer,
int id_peer_len,
259 BIGNUM *x_candidate = NULL, *rnd = NULL, *y_sqrd = NULL, *qr = NULL, *qnr = NULL, *y1 = NULL, *y2 = NULL, *
y = NULL, *exp = NULL;
260 EVP_MD_CTX *hmac_ctx;
262 uint8_t pwe_digest[SHA256_DIGEST_LENGTH], *prfbuf = NULL, *xbuf = NULL, *pm1buf = NULL, *y1buf = NULL, *y2buf = NULL, *ybuf = NULL, ctr;
263 int nid, is_odd, primebitlen, primebytelen, ret = 0, found = 0,
mask;
264 int save, i, rbits, qr_or_qnr, save_is_odd = 0, cmp;
267 MEM(hmac_ctx = EVP_MD_CTX_new());
268 MEM(hmac_pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL,
allzero,
sizeof(
allzero)));
272 nid = NID_X9_62_prime256v1;
284 nid = NID_X9_62_prime192v1;
292 DEBUG(
"unknown group %d", grp_num);
297 session->
order = NULL;
298 session->
prime = NULL;
300 if ((session->
group = EC_GROUP_new_by_curve_name(nid)) == NULL) {
301 DEBUG(
"unable to create EC_GROUP");
306 ((session->
pwe = EC_POINT_new(session->
group)) == NULL) ||
317 DEBUG(
"unable to create bignums");
321 if (!EC_GROUP_get_curve(session->
group, session->
prime, NULL, NULL, NULL)) {
322 DEBUG(
"unable to get prime for GFp curve");
326 if (!EC_GROUP_get_order(session->
group, session->
order, NULL)) {
327 DEBUG(
"unable to get order for curve");
331 primebitlen = BN_num_bits(session->
prime);
332 primebytelen = BN_num_bytes(session->
prime);
333 if ((prfbuf = talloc_zero_array(session,
uint8_t, primebytelen)) == NULL) {
334 DEBUG(
"unable to alloc space for prf buffer");
337 if ((xbuf = talloc_zero_array(request,
uint8_t, primebytelen)) == NULL) {
338 DEBUG(
"unable to alloc space for x buffer");
341 if ((pm1buf = talloc_zero_array(request,
uint8_t, primebytelen)) == NULL) {
342 DEBUG(
"unable to alloc space for pm1 buffer");
345 if ((y1buf = talloc_zero_array(request,
uint8_t, primebytelen)) == NULL) {
346 DEBUG(
"unable to alloc space for y1 buffer");
349 if ((y2buf = talloc_zero_array(request,
uint8_t, primebytelen)) == NULL) {
350 DEBUG(
"unable to alloc space for y2 buffer");
353 if ((ybuf = talloc_zero_array(request,
uint8_t, primebytelen)) == NULL) {
354 DEBUG(
"unable to alloc space for y buffer");
363 BN_rand_range(qr, session->
prime);
367 BN_rand_range(qnr, session->
prime);
370 if (!BN_sub(rnd, session->
prime, BN_value_one())) {
373 BN_bn2bin(rnd, pm1buf);
377 memset(xbuf, 0, primebytelen);
387 EVP_DigestSignInit(hmac_ctx, NULL, EVP_sha256(), NULL, hmac_pkey);
388 EVP_DigestSignUpdate(hmac_ctx, (
uint8_t *)token,
sizeof(*token));
389 EVP_DigestSignUpdate(hmac_ctx, (
uint8_t const *)id_peer, id_peer_len);
390 EVP_DigestSignUpdate(hmac_ctx, (
uint8_t const *)id_server, id_server_len);
391 EVP_DigestSignUpdate(hmac_ctx, (
uint8_t const *)password, password_len);
392 EVP_DigestSignUpdate(hmac_ctx, (
uint8_t *)&ctr,
sizeof(ctr));
395 BN_bin2bn(pwe_digest, SHA256_DIGEST_LENGTH, rnd);
396 eap_pwd_kdf(pwe_digest, SHA256_DIGEST_LENGTH,
"EAP-pwd Hunting And Pecking",
397 strlen(
"EAP-pwd Hunting And Pecking"), prfbuf, primebitlen);
406 if (primebitlen % 8) {
407 rbits = 8 - (primebitlen % 8);
408 for (i = primebytelen - 1; i > 0; i--) {
409 prfbuf[i] = (prfbuf[i - 1] << (8 - rbits)) | (prfbuf[i] >> rbits);
413 BN_bin2bn(prfbuf, primebytelen, x_candidate);
427 is_odd = BN_is_odd(rnd);
469 BN_bin2bn(xbuf, primebytelen, x_candidate);
471 if ( !BN_add(exp, session->
prime, BN_value_one()) ||
472 !BN_rshift(exp, exp, 2) ||
473 !BN_mod_exp_mont_consttime(y1, y_sqrd, exp, session->
prime, bnctx, NULL) ||
474 !BN_sub(y2, session->
prime, y1) ||
475 !BN_bn2bin(y1, y1buf) ||
476 !BN_bn2bin(y2, y2buf)) {
477 DEBUG(
"unable to compute y");
482 if (BN_bin2bn(ybuf, primebytelen,
y) == NULL ||
483 !EC_POINT_set_affine_coordinates(session->
group, session->
pwe, x_candidate,
y, bnctx)) {
484 DEBUG(
"unable to set point coordinate");
495 BN_clear_free(x_candidate);
496 BN_clear_free(y_sqrd);
512 EVP_MD_CTX_free(hmac_ctx);
513 EVP_PKEY_free(hmac_pkey);
530 REDEBUG(
"Unable to get randomness for private_value");
533 if (BN_rand_range(
mask, session->
order) != 1) {
534 REDEBUG(
"Unable to get randomness for mask");
541 REDEBUG(
"Server element allocation failed");
546 REDEBUG(
"Server element inversion failed");
562 BIGNUM *x = NULL, *
y = NULL, *cofactor = NULL;
563 EC_POINT *K = NULL, *point = NULL;
567 MEM(session->
k = BN_new());
569 MEM(point = EC_POINT_new(session->
group));
570 MEM(K = EC_POINT_new(session->
group));
572 MEM(cofactor = BN_new());
576 if (!EC_GROUP_get_cofactor(session->
group, cofactor, NULL)) {
577 REDEBUG(
"Unable to get group co-factor");
583 data_len = BN_num_bytes(session->
prime);
588 if (in_len < (2 * data_len + BN_num_bytes(session->
order))) {
589 REDEBUG(
"Invalid commit packet");
593 BN_bin2bn(ptr, data_len, x);
595 BN_bin2bn(ptr, data_len,
y);
598 data_len = BN_num_bytes(session->
order);
605 REDEBUG(
"Peer's scalar is not within the allowed range");
609 if (!EC_POINT_set_affine_coordinates(session->
group, session->
peer_element, x,
y, bn_ctx)) {
610 REDEBUG(
"Unable to get coordinates of peer's element");
617 REDEBUG(
"Peer's element is not a point on the elliptic curve");
622 if (BN_cmp(cofactor, BN_value_one())) {
623 if (!EC_POINT_mul(session->
group, point, NULL, session->
peer_element, cofactor, NULL)) {
624 REDEBUG(
"Unable to multiply element by co-factor");
628 if (EC_POINT_is_at_infinity(session->
group, point)) {
629 REDEBUG(
"Peer's element is in small sub-group");
637 REDEBUG(
"Reflection attack detected");
642 if ((!EC_POINT_mul(session->
group, K, NULL, session->
pwe, session->
peer_scalar, bn_ctx)) ||
645 REDEBUG(
"Unable to compute shared key, k");
650 if (BN_cmp(cofactor, BN_value_one())) {
651 if (!EC_POINT_mul(session->
group, K, NULL, K, cofactor, NULL)) {
652 REDEBUG(
"Unable to multiply k by co-factor");
663 if (EC_POINT_is_at_infinity(session->
group, K)) {
664 REDEBUG(
"K is point-at-infinity");
668 if (!EC_POINT_get_affine_coordinates(session->
group, K, session->
k, NULL, bn_ctx)) {
669 REDEBUG(
"Unable to get shared secret from K");
675 EC_POINT_clear_free(K);
676 EC_POINT_clear_free(point);
677 BN_clear_free(cofactor);
686 BIGNUM *x = NULL, *
y = NULL;
687 EVP_MD_CTX *hmac_ctx;
690 int offset, req = -1;
695 MEM(cruft = talloc_zero_array(session,
uint8_t, BN_num_bytes(session->
prime)));
703 MEM(hmac_ctx = EVP_MD_CTX_new());
704 MEM(hmac_pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL,
allzero,
sizeof(
allzero)));
705 EVP_DigestSignInit(hmac_ctx, NULL, EVP_sha256(), NULL, hmac_pkey);
713 offset = BN_num_bytes(session->
prime) - BN_num_bytes(session->
k);
714 BN_bn2bin(session->
k, cruft + offset);
715 EVP_DigestSignUpdate(hmac_ctx, cruft, BN_num_bytes(session->
prime));
720 if (!EC_POINT_get_affine_coordinates(session->
group, session->
my_element, x,
y, bn_ctx)) {
721 REDEBUG(
"Unable to get coordinates of server element");
724 memset(cruft, 0, BN_num_bytes(session->
prime));
725 offset = BN_num_bytes(session->
prime) - BN_num_bytes(x);
726 BN_bn2bin(x, cruft + offset);
727 EVP_DigestSignUpdate(hmac_ctx, cruft, BN_num_bytes(session->
prime));
729 memset(cruft, 0, BN_num_bytes(session->
prime));
730 offset = BN_num_bytes(session->
prime) - BN_num_bytes(
y);
731 BN_bn2bin(
y, cruft + offset);
732 EVP_DigestSignUpdate(hmac_ctx, cruft, BN_num_bytes(session->
prime));
737 memset(cruft, 0, BN_num_bytes(session->
prime));
738 offset = BN_num_bytes(session->
order) - BN_num_bytes(session->
my_scalar);
739 BN_bn2bin(session->
my_scalar, cruft + offset);
740 EVP_DigestSignUpdate(hmac_ctx, cruft, BN_num_bytes(session->
order));
745 if (!EC_POINT_get_affine_coordinates(session->
group, session->
peer_element, x,
y, bn_ctx)) {
746 REDEBUG(
"Unable to get coordinates of peer's element");
750 memset(cruft, 0, BN_num_bytes(session->
prime));
751 offset = BN_num_bytes(session->
prime) - BN_num_bytes(x);
752 BN_bn2bin(x, cruft + offset);
753 EVP_DigestSignUpdate(hmac_ctx, cruft, BN_num_bytes(session->
prime));
755 memset(cruft, 0, BN_num_bytes(session->
prime));
756 offset = BN_num_bytes(session->
prime) - BN_num_bytes(
y);
757 BN_bn2bin(
y, cruft + offset);
758 EVP_DigestSignUpdate(hmac_ctx, cruft, BN_num_bytes(session->
prime));
763 memset(cruft, 0, BN_num_bytes(session->
prime));
766 EVP_DigestSignUpdate(hmac_ctx, cruft, BN_num_bytes(session->
order));
778 EVP_MD_CTX_free(hmac_ctx);
779 EVP_PKEY_free(hmac_pkey);
789 BIGNUM *x = NULL, *
y = NULL;
790 EVP_MD_CTX *hmac_ctx;
793 int offset, req = -1;
798 MEM(cruft = talloc_zero_array(session,
uint8_t, BN_num_bytes(session->
prime)));
806 MEM(hmac_ctx = EVP_MD_CTX_new());
807 MEM(hmac_pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL,
allzero,
sizeof(
allzero)));
808 EVP_DigestSignInit(hmac_ctx, NULL, EVP_sha256(), NULL, hmac_pkey);
816 offset = BN_num_bytes(session->
prime) - BN_num_bytes(session->
k);
817 BN_bn2bin(session->
k, cruft + offset);
818 EVP_DigestSignUpdate(hmac_ctx, cruft, BN_num_bytes(session->
prime));
823 if (!EC_POINT_get_affine_coordinates(session->
group, session->
peer_element, x,
y, bn_ctx)) {
824 REDEBUG(
"Unable to get coordinates of peer's element");
828 memset(cruft, 0, BN_num_bytes(session->
prime));
829 offset = BN_num_bytes(session->
prime) - BN_num_bytes(x);
830 BN_bn2bin(x, cruft + offset);
831 EVP_DigestSignUpdate(hmac_ctx, cruft, BN_num_bytes(session->
prime));
833 memset(cruft, 0, BN_num_bytes(session->
prime));
834 offset = BN_num_bytes(session->
prime) - BN_num_bytes(
y);
835 BN_bn2bin(
y, cruft + offset);
836 EVP_DigestSignUpdate(hmac_ctx, cruft, BN_num_bytes(session->
prime));
841 memset(cruft, 0, BN_num_bytes(session->
prime));
844 EVP_DigestSignUpdate(hmac_ctx, cruft, BN_num_bytes(session->
order));
849 if (!EC_POINT_get_affine_coordinates(session->
group, session->
my_element, x,
y, bn_ctx)) {
850 REDEBUG(
"Unable to get coordinates of server element");
853 memset(cruft, 0, BN_num_bytes(session->
prime));
854 offset = BN_num_bytes(session->
prime) - BN_num_bytes(x);
855 BN_bn2bin(x, cruft + offset);
856 EVP_DigestSignUpdate(hmac_ctx, cruft, BN_num_bytes(session->
prime));
858 memset(cruft, 0, BN_num_bytes(session->
prime));
859 offset = BN_num_bytes(session->
prime) - BN_num_bytes(
y);
860 BN_bn2bin(
y, cruft + offset);
861 EVP_DigestSignUpdate(hmac_ctx, cruft, BN_num_bytes(session->
prime));
866 memset(cruft, 0, BN_num_bytes(session->
prime));
867 offset = BN_num_bytes(session->
order) - BN_num_bytes(session->
my_scalar);
868 BN_bn2bin(session->
my_scalar, cruft + offset);
869 EVP_DigestSignUpdate(hmac_ctx, cruft, BN_num_bytes(session->
order));
880 EVP_MD_CTX_free(hmac_ctx);
881 EVP_PKEY_free(hmac_pkey);
891 EVP_MD_CTX *hmac_ctx;
893 uint8_t mk[SHA256_DIGEST_LENGTH], *cruft;
894 uint8_t session_id[SHA256_DIGEST_LENGTH + 1];
898 MEM(cruft = talloc_array(session,
uint8_t, BN_num_bytes(session->
prime)));
899 MEM(hmac_ctx = EVP_MD_CTX_new());
900 MEM(hmac_pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL,
allzero,
sizeof(
allzero)));
907 EVP_DigestSignInit(hmac_ctx, NULL, EVP_sha256(), NULL, hmac_pkey);
910 memset(cruft, 0, BN_num_bytes(session->
prime));
912 EVP_DigestSignUpdate(hmac_ctx, cruft, BN_num_bytes(session->
order));
913 offset = BN_num_bytes(session->
order) - BN_num_bytes(session->
my_scalar);
914 memset(cruft, 0, BN_num_bytes(session->
prime));
915 BN_bn2bin(session->
my_scalar, cruft + offset);
916 EVP_DigestSignUpdate(hmac_ctx, cruft, BN_num_bytes(session->
order));
920 EVP_DigestSignInit(hmac_ctx, NULL, EVP_sha256(), NULL, hmac_pkey);
922 memset(cruft, 0, BN_num_bytes(session->
prime));
923 offset = BN_num_bytes(session->
prime) - BN_num_bytes(session->
k);
924 BN_bn2bin(session->
k, cruft + offset);
925 EVP_DigestSignUpdate(hmac_ctx, cruft, BN_num_bytes(session->
prime));
927 EVP_DigestSignUpdate(hmac_ctx, peer_confirm, SHA256_DIGEST_LENGTH);
929 EVP_DigestSignUpdate(hmac_ctx, session->
my_confirm, SHA256_DIGEST_LENGTH);
934 eap_pwd_kdf(mk, SHA256_DIGEST_LENGTH, (
char const *)session_id,
935 SHA256_DIGEST_LENGTH + 1, msk_emsk, 1024);
937 memcpy(msk, msk_emsk, 64);
938 memcpy(emsk, msk_emsk + 64, 64);
940 EVP_MD_CTX_free(hmac_ctx);
941 EVP_PKEY_free(hmac_pkey);
#define USES_APPLE_DEPRECATED_API
#define L(_str)
Helper for initialising arrays of string literals.
static int const_time_select_int(unsigned int mask, int true_val, int false_val)
const_time_select_int - Constant time int selection
static void const_time_select_bin(unsigned char mask, const unsigned char *true_val, const unsigned char *false_val, size_t len, unsigned char *dst)
const_time_select_bin - Constant time binary buffer selection copy
static unsigned int const_time_is_zero(unsigned int val) NO_UBSAN_UINT_OVERFLOW
static unsigned int const_time_eq(unsigned int a, unsigned int b)
static int const_time_memcmp(const void *a, const void *b, size_t len)
static unsigned int const_time_fill_msb(unsigned int val)
const_time_fill_msb - Fill all bits with MSB value
static unsigned int const_time_select(unsigned int mask, unsigned int true_val, unsigned int false_val)
const_time_select - Constant time unsigned int selection
static int legendre(BIGNUM *a, BIGNUM *p, BN_CTX *bnctx)
int compute_scalar_element(request_t *request, pwd_session_t *session, BN_CTX *bn_ctx)
static int is_quadratic_residue(BIGNUM *val, BIGNUM *p, BIGNUM *qr, BIGNUM *qnr, BN_CTX *bnctx)
int process_peer_commit(request_t *request, pwd_session_t *session, uint8_t *in, size_t in_len, BN_CTX *bn_ctx)
int compute_server_confirm(request_t *request, pwd_session_t *session, uint8_t *out, BN_CTX *bn_ctx)
static void pwd_hmac_final(EVP_MD_CTX *hmac_ctx, uint8_t digest[static SHA256_DIGEST_LENGTH])
int compute_keys(UNUSED request_t *request, pwd_session_t *session, uint8_t *peer_confirm, uint8_t *msk, uint8_t *emsk)
static void eap_pwd_kdf(uint8_t *key, int keylen, char const *label, int label_len, uint8_t *result, int result_bit_len)
static USES_APPLE_DEPRECATED_API uint8_t allzero[SHA256_DIGEST_LENGTH]
copyright holder grants permission for redistribution and use in source and binary forms,...
int compute_password_element(request_t *request, pwd_session_t *session, uint16_t grp_num, char const *password, int password_len, char const *id_server, int id_server_len, char const *id_peer, int id_peer_len, uint32_t *token, BN_CTX *bnctx)
int compute_peer_confirm(request_t *request, pwd_session_t *session, uint8_t *out, BN_CTX *bn_ctx)
static BIGNUM * consttime_BN(void)
static void do_equation(EC_GROUP *group, BIGNUM *y2, BIGNUM *x, BN_CTX *bnctx)
uint8_t my_confirm[SHA256_DIGEST_LENGTH]
#define check(_handle, _len_p)
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
static size_t char ** out