/src/openssl111/crypto/srp/srp_lib.c
| Line | Count | Source (jump to first uncovered line) | 
| 1 |  | /* | 
| 2 |  |  * Copyright 2004-2021 The OpenSSL Project Authors. All Rights Reserved. | 
| 3 |  |  * Copyright (c) 2004, EdelKey Project. All Rights Reserved. | 
| 4 |  |  * | 
| 5 |  |  * Licensed under the OpenSSL license (the "License").  You may not use | 
| 6 |  |  * this file except in compliance with the License.  You can obtain a copy | 
| 7 |  |  * in the file LICENSE in the source distribution or at | 
| 8 |  |  * https://www.openssl.org/source/license.html | 
| 9 |  |  * | 
| 10 |  |  * Originally written by Christophe Renou and Peter Sylvester, | 
| 11 |  |  * for the EdelKey project. | 
| 12 |  |  */ | 
| 13 |  |  | 
| 14 |  | #ifndef OPENSSL_NO_SRP | 
| 15 |  | # include "internal/cryptlib.h" | 
| 16 |  | # include <openssl/sha.h> | 
| 17 |  | # include <openssl/srp.h> | 
| 18 |  | # include <openssl/evp.h> | 
| 19 |  | # include "crypto/bn_srp.h" | 
| 20 |  |  | 
| 21 |  | /* calculate = SHA1(PAD(x) || PAD(y)) */ | 
| 22 |  |  | 
| 23 |  | static BIGNUM *srp_Calc_xy(const BIGNUM *x, const BIGNUM *y, const BIGNUM *N) | 
| 24 | 0 | { | 
| 25 | 0 |     unsigned char digest[SHA_DIGEST_LENGTH]; | 
| 26 | 0 |     unsigned char *tmp = NULL; | 
| 27 | 0 |     int numN = BN_num_bytes(N); | 
| 28 | 0 |     BIGNUM *res = NULL; | 
| 29 |  | 
 | 
| 30 | 0 |     if (x != N && BN_ucmp(x, N) >= 0) | 
| 31 | 0 |         return NULL; | 
| 32 | 0 |     if (y != N && BN_ucmp(y, N) >= 0) | 
| 33 | 0 |         return NULL; | 
| 34 | 0 |     if ((tmp = OPENSSL_malloc(numN * 2)) == NULL) | 
| 35 | 0 |         goto err; | 
| 36 | 0 |     if (BN_bn2binpad(x, tmp, numN) < 0 | 
| 37 | 0 |         || BN_bn2binpad(y, tmp + numN, numN) < 0 | 
| 38 | 0 |         || !EVP_Digest(tmp, numN * 2, digest, NULL, EVP_sha1(), NULL)) | 
| 39 | 0 |         goto err; | 
| 40 | 0 |     res = BN_bin2bn(digest, sizeof(digest), NULL); | 
| 41 | 0 |  err: | 
| 42 | 0 |     OPENSSL_free(tmp); | 
| 43 | 0 |     return res; | 
| 44 | 0 | } | 
| 45 |  |  | 
| 46 |  | static BIGNUM *srp_Calc_k(const BIGNUM *N, const BIGNUM *g) | 
| 47 | 0 | { | 
| 48 |  |     /* k = SHA1(N | PAD(g)) -- tls-srp draft 8 */ | 
| 49 | 0 |     return srp_Calc_xy(N, g, N); | 
| 50 | 0 | } | 
| 51 |  |  | 
| 52 |  | BIGNUM *SRP_Calc_u(const BIGNUM *A, const BIGNUM *B, const BIGNUM *N) | 
| 53 | 0 | { | 
| 54 |  |     /* k = SHA1(PAD(A) || PAD(B) ) -- tls-srp draft 8 */ | 
| 55 | 0 |     return srp_Calc_xy(A, B, N); | 
| 56 | 0 | } | 
| 57 |  |  | 
| 58 |  | BIGNUM *SRP_Calc_server_key(const BIGNUM *A, const BIGNUM *v, const BIGNUM *u, | 
| 59 |  |                             const BIGNUM *b, const BIGNUM *N) | 
| 60 | 0 | { | 
| 61 | 0 |     BIGNUM *tmp = NULL, *S = NULL; | 
| 62 | 0 |     BN_CTX *bn_ctx; | 
| 63 |  | 
 | 
| 64 | 0 |     if (u == NULL || A == NULL || v == NULL || b == NULL || N == NULL) | 
| 65 | 0 |         return NULL; | 
| 66 |  |  | 
| 67 | 0 |     if ((bn_ctx = BN_CTX_new()) == NULL || (tmp = BN_new()) == NULL) | 
| 68 | 0 |         goto err; | 
| 69 |  |  | 
| 70 |  |     /* S = (A*v**u) ** b */ | 
| 71 |  |  | 
| 72 | 0 |     if (!BN_mod_exp(tmp, v, u, N, bn_ctx)) | 
| 73 | 0 |         goto err; | 
| 74 | 0 |     if (!BN_mod_mul(tmp, A, tmp, N, bn_ctx)) | 
| 75 | 0 |         goto err; | 
| 76 |  |  | 
| 77 | 0 |     S = BN_new(); | 
| 78 | 0 |     if (S != NULL && !BN_mod_exp(S, tmp, b, N, bn_ctx)) { | 
| 79 | 0 |         BN_free(S); | 
| 80 | 0 |         S = NULL; | 
| 81 | 0 |     } | 
| 82 | 0 |  err: | 
| 83 | 0 |     BN_CTX_free(bn_ctx); | 
| 84 | 0 |     BN_clear_free(tmp); | 
| 85 | 0 |     return S; | 
| 86 | 0 | } | 
| 87 |  |  | 
| 88 |  | BIGNUM *SRP_Calc_B(const BIGNUM *b, const BIGNUM *N, const BIGNUM *g, | 
| 89 |  |                    const BIGNUM *v) | 
| 90 | 0 | { | 
| 91 | 0 |     BIGNUM *kv = NULL, *gb = NULL; | 
| 92 | 0 |     BIGNUM *B = NULL, *k = NULL; | 
| 93 | 0 |     BN_CTX *bn_ctx; | 
| 94 |  | 
 | 
| 95 | 0 |     if (b == NULL || N == NULL || g == NULL || v == NULL || | 
| 96 | 0 |         (bn_ctx = BN_CTX_new()) == NULL) | 
| 97 | 0 |         return NULL; | 
| 98 |  |  | 
| 99 | 0 |     if ((kv = BN_new()) == NULL || | 
| 100 | 0 |         (gb = BN_new()) == NULL || (B = BN_new()) == NULL) | 
| 101 | 0 |         goto err; | 
| 102 |  |  | 
| 103 |  |     /* B = g**b + k*v */ | 
| 104 |  |  | 
| 105 | 0 |     if (!BN_mod_exp(gb, g, b, N, bn_ctx) | 
| 106 | 0 |         || (k = srp_Calc_k(N, g)) == NULL | 
| 107 | 0 |         || !BN_mod_mul(kv, v, k, N, bn_ctx) | 
| 108 | 0 |         || !BN_mod_add(B, gb, kv, N, bn_ctx)) { | 
| 109 | 0 |         BN_free(B); | 
| 110 | 0 |         B = NULL; | 
| 111 | 0 |     } | 
| 112 | 0 |  err: | 
| 113 | 0 |     BN_CTX_free(bn_ctx); | 
| 114 | 0 |     BN_clear_free(kv); | 
| 115 | 0 |     BN_clear_free(gb); | 
| 116 | 0 |     BN_free(k); | 
| 117 | 0 |     return B; | 
| 118 | 0 | } | 
| 119 |  |  | 
| 120 |  | BIGNUM *SRP_Calc_x(const BIGNUM *s, const char *user, const char *pass) | 
| 121 | 0 | { | 
| 122 | 0 |     unsigned char dig[SHA_DIGEST_LENGTH]; | 
| 123 | 0 |     EVP_MD_CTX *ctxt; | 
| 124 | 0 |     unsigned char *cs = NULL; | 
| 125 | 0 |     BIGNUM *res = NULL; | 
| 126 |  | 
 | 
| 127 | 0 |     if ((s == NULL) || (user == NULL) || (pass == NULL)) | 
| 128 | 0 |         return NULL; | 
| 129 |  |  | 
| 130 | 0 |     ctxt = EVP_MD_CTX_new(); | 
| 131 | 0 |     if (ctxt == NULL) | 
| 132 | 0 |         return NULL; | 
| 133 | 0 |     if ((cs = OPENSSL_malloc(BN_num_bytes(s))) == NULL) | 
| 134 | 0 |         goto err; | 
| 135 |  |  | 
| 136 | 0 |     if (!EVP_DigestInit_ex(ctxt, EVP_sha1(), NULL) | 
| 137 | 0 |         || !EVP_DigestUpdate(ctxt, user, strlen(user)) | 
| 138 | 0 |         || !EVP_DigestUpdate(ctxt, ":", 1) | 
| 139 | 0 |         || !EVP_DigestUpdate(ctxt, pass, strlen(pass)) | 
| 140 | 0 |         || !EVP_DigestFinal_ex(ctxt, dig, NULL) | 
| 141 | 0 |         || !EVP_DigestInit_ex(ctxt, EVP_sha1(), NULL)) | 
| 142 | 0 |         goto err; | 
| 143 | 0 |     if (BN_bn2bin(s, cs) < 0) | 
| 144 | 0 |         goto err; | 
| 145 | 0 |     if (!EVP_DigestUpdate(ctxt, cs, BN_num_bytes(s))) | 
| 146 | 0 |         goto err; | 
| 147 |  |  | 
| 148 | 0 |     if (!EVP_DigestUpdate(ctxt, dig, sizeof(dig)) | 
| 149 | 0 |         || !EVP_DigestFinal_ex(ctxt, dig, NULL)) | 
| 150 | 0 |         goto err; | 
| 151 |  |  | 
| 152 | 0 |     res = BN_bin2bn(dig, sizeof(dig), NULL); | 
| 153 |  | 
 | 
| 154 | 0 |  err: | 
| 155 | 0 |     OPENSSL_free(cs); | 
| 156 | 0 |     EVP_MD_CTX_free(ctxt); | 
| 157 | 0 |     return res; | 
| 158 | 0 | } | 
| 159 |  |  | 
| 160 |  | BIGNUM *SRP_Calc_A(const BIGNUM *a, const BIGNUM *N, const BIGNUM *g) | 
| 161 | 0 | { | 
| 162 | 0 |     BN_CTX *bn_ctx; | 
| 163 | 0 |     BIGNUM *A = NULL; | 
| 164 |  | 
 | 
| 165 | 0 |     if (a == NULL || N == NULL || g == NULL || (bn_ctx = BN_CTX_new()) == NULL) | 
| 166 | 0 |         return NULL; | 
| 167 |  |  | 
| 168 | 0 |     if ((A = BN_new()) != NULL && !BN_mod_exp(A, g, a, N, bn_ctx)) { | 
| 169 | 0 |         BN_free(A); | 
| 170 | 0 |         A = NULL; | 
| 171 | 0 |     } | 
| 172 | 0 |     BN_CTX_free(bn_ctx); | 
| 173 | 0 |     return A; | 
| 174 | 0 | } | 
| 175 |  |  | 
| 176 |  | BIGNUM *SRP_Calc_client_key(const BIGNUM *N, const BIGNUM *B, const BIGNUM *g, | 
| 177 |  |                             const BIGNUM *x, const BIGNUM *a, const BIGNUM *u) | 
| 178 | 0 | { | 
| 179 | 0 |     BIGNUM *tmp = NULL, *tmp2 = NULL, *tmp3 = NULL, *k = NULL, *K = NULL; | 
| 180 | 0 |     BIGNUM *xtmp = NULL; | 
| 181 | 0 |     BN_CTX *bn_ctx; | 
| 182 |  | 
 | 
| 183 | 0 |     if (u == NULL || B == NULL || N == NULL || g == NULL || x == NULL | 
| 184 | 0 |         || a == NULL || (bn_ctx = BN_CTX_new()) == NULL) | 
| 185 | 0 |         return NULL; | 
| 186 |  |  | 
| 187 | 0 |     if ((tmp = BN_new()) == NULL || | 
| 188 | 0 |         (tmp2 = BN_new()) == NULL || | 
| 189 | 0 |         (tmp3 = BN_new()) == NULL || | 
| 190 | 0 |         (xtmp = BN_new()) == NULL) | 
| 191 | 0 |         goto err; | 
| 192 |  |  | 
| 193 | 0 |     BN_with_flags(xtmp, x, BN_FLG_CONSTTIME); | 
| 194 | 0 |     BN_set_flags(tmp, BN_FLG_CONSTTIME); | 
| 195 | 0 |     if (!BN_mod_exp(tmp, g, xtmp, N, bn_ctx)) | 
| 196 | 0 |         goto err; | 
| 197 | 0 |     if ((k = srp_Calc_k(N, g)) == NULL) | 
| 198 | 0 |         goto err; | 
| 199 | 0 |     if (!BN_mod_mul(tmp2, tmp, k, N, bn_ctx)) | 
| 200 | 0 |         goto err; | 
| 201 | 0 |     if (!BN_mod_sub(tmp, B, tmp2, N, bn_ctx)) | 
| 202 | 0 |         goto err; | 
| 203 | 0 |     if (!BN_mul(tmp3, u, xtmp, bn_ctx)) | 
| 204 | 0 |         goto err; | 
| 205 | 0 |     if (!BN_add(tmp2, a, tmp3)) | 
| 206 | 0 |         goto err; | 
| 207 | 0 |     K = BN_new(); | 
| 208 | 0 |     if (K != NULL && !BN_mod_exp(K, tmp, tmp2, N, bn_ctx)) { | 
| 209 | 0 |         BN_free(K); | 
| 210 | 0 |         K = NULL; | 
| 211 | 0 |     } | 
| 212 |  | 
 | 
| 213 | 0 |  err: | 
| 214 | 0 |     BN_CTX_free(bn_ctx); | 
| 215 | 0 |     BN_free(xtmp); | 
| 216 | 0 |     BN_clear_free(tmp); | 
| 217 | 0 |     BN_clear_free(tmp2); | 
| 218 | 0 |     BN_clear_free(tmp3); | 
| 219 | 0 |     BN_free(k); | 
| 220 | 0 |     return K; | 
| 221 | 0 | } | 
| 222 |  |  | 
| 223 |  | int SRP_Verify_B_mod_N(const BIGNUM *B, const BIGNUM *N) | 
| 224 | 0 | { | 
| 225 | 0 |     BIGNUM *r; | 
| 226 | 0 |     BN_CTX *bn_ctx; | 
| 227 | 0 |     int ret = 0; | 
| 228 |  | 
 | 
| 229 | 0 |     if (B == NULL || N == NULL || (bn_ctx = BN_CTX_new()) == NULL) | 
| 230 | 0 |         return 0; | 
| 231 |  |  | 
| 232 | 0 |     if ((r = BN_new()) == NULL) | 
| 233 | 0 |         goto err; | 
| 234 |  |     /* Checks if B % N == 0 */ | 
| 235 | 0 |     if (!BN_nnmod(r, B, N, bn_ctx)) | 
| 236 | 0 |         goto err; | 
| 237 | 0 |     ret = !BN_is_zero(r); | 
| 238 | 0 |  err: | 
| 239 | 0 |     BN_CTX_free(bn_ctx); | 
| 240 | 0 |     BN_free(r); | 
| 241 | 0 |     return ret; | 
| 242 | 0 | } | 
| 243 |  |  | 
| 244 |  | int SRP_Verify_A_mod_N(const BIGNUM *A, const BIGNUM *N) | 
| 245 | 0 | { | 
| 246 |  |     /* Checks if A % N == 0 */ | 
| 247 | 0 |     return SRP_Verify_B_mod_N(A, N); | 
| 248 | 0 | } | 
| 249 |  |  | 
| 250 |  | static SRP_gN knowngN[] = { | 
| 251 |  |     {"8192", &bn_generator_19, &bn_group_8192}, | 
| 252 |  |     {"6144", &bn_generator_5, &bn_group_6144}, | 
| 253 |  |     {"4096", &bn_generator_5, &bn_group_4096}, | 
| 254 |  |     {"3072", &bn_generator_5, &bn_group_3072}, | 
| 255 |  |     {"2048", &bn_generator_2, &bn_group_2048}, | 
| 256 |  |     {"1536", &bn_generator_2, &bn_group_1536}, | 
| 257 |  |     {"1024", &bn_generator_2, &bn_group_1024}, | 
| 258 |  | }; | 
| 259 |  |  | 
| 260 | 0 | # define KNOWN_GN_NUMBER sizeof(knowngN) / sizeof(SRP_gN) | 
| 261 |  |  | 
| 262 |  | /* | 
| 263 |  |  * Check if G and N are known parameters. The values have been generated | 
| 264 |  |  * from the ietf-tls-srp draft version 8 | 
| 265 |  |  */ | 
| 266 |  | char *SRP_check_known_gN_param(const BIGNUM *g, const BIGNUM *N) | 
| 267 | 0 | { | 
| 268 | 0 |     size_t i; | 
| 269 | 0 |     if ((g == NULL) || (N == NULL)) | 
| 270 | 0 |         return 0; | 
| 271 |  |  | 
| 272 | 0 |     for (i = 0; i < KNOWN_GN_NUMBER; i++) { | 
| 273 | 0 |         if (BN_cmp(knowngN[i].g, g) == 0 && BN_cmp(knowngN[i].N, N) == 0) | 
| 274 | 0 |             return knowngN[i].id; | 
| 275 | 0 |     } | 
| 276 | 0 |     return NULL; | 
| 277 | 0 | } | 
| 278 |  |  | 
| 279 |  | SRP_gN *SRP_get_default_gN(const char *id) | 
| 280 | 0 | { | 
| 281 | 0 |     size_t i; | 
| 282 |  | 
 | 
| 283 | 0 |     if (id == NULL) | 
| 284 | 0 |         return knowngN; | 
| 285 | 0 |     for (i = 0; i < KNOWN_GN_NUMBER; i++) { | 
| 286 | 0 |         if (strcmp(knowngN[i].id, id) == 0) | 
| 287 | 0 |             return knowngN + i; | 
| 288 | 0 |     } | 
| 289 | 0 |     return NULL; | 
| 290 | 0 | } | 
| 291 |  | #endif |