srp_lib.c 7.3 KB
Newer Older
1
/*
T
Tim Hudson 已提交
2 3
 * Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved.
 * Copyright (c) 2004, EdelKey Project. All Rights Reserved.
B
Ben Laurie 已提交
4
 *
R
Rich Salz 已提交
5 6 7 8
 * Licensed under the OpenSSL license (the "License").  You may not use
 * this file except in compliance with the License.  You can obtain a copy
 * in the file LICENSE in the source distribution or at
 * https://www.openssl.org/source/license.html
T
Tim Hudson 已提交
9 10 11
 *
 * Originally written by Christophe Renou and Peter Sylvester,
 * for the EdelKey project.
B
Ben Laurie 已提交
12
 */
R
Rich Salz 已提交
13

B
Ben Laurie 已提交
14
#ifndef OPENSSL_NO_SRP
15
# include "internal/cryptlib.h"
16
# include <openssl/sha.h>
17 18 19
# include <openssl/srp.h>
# include <openssl/evp.h>
# include "internal/bn_srp.h"
B
Ben Laurie 已提交
20

D
Dr. Stephen Henson 已提交
21
/* calculate = SHA1(PAD(x) || PAD(y)) */
22

D
Dr. Stephen Henson 已提交
23 24
static BIGNUM *srp_Calc_xy(const BIGNUM *x, const BIGNUM *y, const BIGNUM *N)
{
25
    unsigned char digest[SHA_DIGEST_LENGTH];
M
Matt Caswell 已提交
26
    unsigned char *tmp = NULL;
D
Dr. Stephen Henson 已提交
27
    int numN = BN_num_bytes(N);
28
    BIGNUM *res = NULL;
29

D
Dr. Stephen Henson 已提交
30
    if (x != N && BN_ucmp(x, N) >= 0)
31
        return NULL;
D
Dr. Stephen Henson 已提交
32
    if (y != N && BN_ucmp(y, N) >= 0)
33
        return NULL;
D
Dr. Stephen Henson 已提交
34
    if ((tmp = OPENSSL_malloc(numN * 2)) == NULL)
35
        goto err;
D
Dr. Stephen Henson 已提交
36 37 38
    if (BN_bn2binpad(x, tmp, numN) < 0
        || BN_bn2binpad(y, tmp + numN, numN) < 0
        || !EVP_Digest(tmp, numN * 2, digest, NULL, EVP_sha1(), NULL))
39
        goto err;
40 41
    res = BN_bin2bn(digest, sizeof(digest), NULL);
 err:
M
Matt Caswell 已提交
42
    OPENSSL_free(tmp);
43
    return res;
44
}
B
Ben Laurie 已提交
45

D
Dr. Stephen Henson 已提交
46 47 48 49 50 51
static BIGNUM *srp_Calc_k(const BIGNUM *N, const BIGNUM *g)
{
    /* k = SHA1(N | PAD(g)) -- tls-srp draft 8 */
    return srp_Calc_xy(N, g, N);
}

M
Matt Caswell 已提交
52
BIGNUM *SRP_Calc_u(const BIGNUM *A, const BIGNUM *B, const BIGNUM *N)
53 54
{
    /* k = SHA1(PAD(A) || PAD(B) ) -- tls-srp draft 8 */
D
Dr. Stephen Henson 已提交
55
    return srp_Calc_xy(A, B, N);
B
Ben Laurie 已提交
56 57
}

M
Matt Caswell 已提交
58 59
BIGNUM *SRP_Calc_server_key(const BIGNUM *A, const BIGNUM *v, const BIGNUM *u,
                            const BIGNUM *b, const BIGNUM *N)
60 61 62 63 64 65 66
{
    BIGNUM *tmp = NULL, *S = NULL;
    BN_CTX *bn_ctx;

    if (u == NULL || A == NULL || v == NULL || b == NULL || N == NULL)
        return NULL;

67
    if ((bn_ctx = BN_CTX_new()) == NULL || (tmp = BN_new()) == NULL)
68 69 70 71 72 73 74 75
        goto err;

    /* S = (A*v**u) ** b */

    if (!BN_mod_exp(tmp, v, u, N, bn_ctx))
        goto err;
    if (!BN_mod_mul(tmp, A, tmp, N, bn_ctx))
        goto err;
76 77 78 79 80 81

    S = BN_new();
    if (S != NULL && !BN_mod_exp(S, tmp, b, N, bn_ctx)) {
        BN_free(S);
        S = NULL;
    }
82 83 84 85 86
 err:
    BN_CTX_free(bn_ctx);
    BN_clear_free(tmp);
    return S;
}
B
Ben Laurie 已提交
87

M
Matt Caswell 已提交
88 89
BIGNUM *SRP_Calc_B(const BIGNUM *b, const BIGNUM *N, const BIGNUM *g,
                   const BIGNUM *v)
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
{
    BIGNUM *kv = NULL, *gb = NULL;
    BIGNUM *B = NULL, *k = NULL;
    BN_CTX *bn_ctx;

    if (b == NULL || N == NULL || g == NULL || v == NULL ||
        (bn_ctx = BN_CTX_new()) == NULL)
        return NULL;

    if ((kv = BN_new()) == NULL ||
        (gb = BN_new()) == NULL || (B = BN_new()) == NULL)
        goto err;

    /* B = g**b + k*v */

105 106 107 108
    if (!BN_mod_exp(gb, g, b, N, bn_ctx)
        || (k = srp_Calc_k(N, g)) == NULL
        || !BN_mod_mul(kv, v, k, N, bn_ctx)
        || !BN_mod_add(B, gb, kv, N, bn_ctx)) {
109 110 111 112 113 114 115 116 117 118
        BN_free(B);
        B = NULL;
    }
 err:
    BN_CTX_free(bn_ctx);
    BN_clear_free(kv);
    BN_clear_free(gb);
    BN_free(k);
    return B;
}
B
Ben Laurie 已提交
119

M
Matt Caswell 已提交
120
BIGNUM *SRP_Calc_x(const BIGNUM *s, const char *user, const char *pass)
121 122
{
    unsigned char dig[SHA_DIGEST_LENGTH];
123
    EVP_MD_CTX *ctxt;
M
Matt Caswell 已提交
124
    unsigned char *cs = NULL;
125
    BIGNUM *res = NULL;
126 127 128 129

    if ((s == NULL) || (user == NULL) || (pass == NULL))
        return NULL;

130
    ctxt = EVP_MD_CTX_new();
131
    if (ctxt == NULL)
132
        return NULL;
133 134
    if ((cs = OPENSSL_malloc(BN_num_bytes(s))) == NULL)
        goto err;
135

136 137 138 139 140 141 142
    if (!EVP_DigestInit_ex(ctxt, EVP_sha1(), NULL)
        || !EVP_DigestUpdate(ctxt, user, strlen(user))
        || !EVP_DigestUpdate(ctxt, ":", 1)
        || !EVP_DigestUpdate(ctxt, pass, strlen(pass))
        || !EVP_DigestFinal_ex(ctxt, dig, NULL)
        || !EVP_DigestInit_ex(ctxt, EVP_sha1(), NULL))
        goto err;
143 144
    if (BN_bn2bin(s, cs) < 0)
        goto err;
145 146
    if (!EVP_DigestUpdate(ctxt, cs, BN_num_bytes(s)))
        goto err;
M
Matt Caswell 已提交
147

148 149 150
    if (!EVP_DigestUpdate(ctxt, dig, sizeof(dig))
        || !EVP_DigestFinal_ex(ctxt, dig, NULL))
        goto err;
151

152
    res = BN_bin2bn(dig, sizeof(dig), NULL);
M
Matt Caswell 已提交
153

154
 err:
M
Matt Caswell 已提交
155
    OPENSSL_free(cs);
156
    EVP_MD_CTX_free(ctxt);
157
    return res;
158
}
B
Ben Laurie 已提交
159

M
Matt Caswell 已提交
160
BIGNUM *SRP_Calc_A(const BIGNUM *a, const BIGNUM *N, const BIGNUM *g)
161 162 163 164
{
    BN_CTX *bn_ctx;
    BIGNUM *A = NULL;

R
Rich Salz 已提交
165
    if (a == NULL || N == NULL || g == NULL || (bn_ctx = BN_CTX_new()) == NULL)
166 167 168 169 170 171 172 173 174 175
        return NULL;

    if ((A = BN_new()) != NULL && !BN_mod_exp(A, g, a, N, bn_ctx)) {
        BN_free(A);
        A = NULL;
    }
    BN_CTX_free(bn_ctx);
    return A;
}

M
Matt Caswell 已提交
176 177
BIGNUM *SRP_Calc_client_key(const BIGNUM *N, const BIGNUM *B, const BIGNUM *g,
                            const BIGNUM *x, const BIGNUM *a, const BIGNUM *u)
178 179 180 181 182 183 184 185 186 187
{
    BIGNUM *tmp = NULL, *tmp2 = NULL, *tmp3 = NULL, *k = NULL, *K = NULL;
    BN_CTX *bn_ctx;

    if (u == NULL || B == NULL || N == NULL || g == NULL || x == NULL
        || a == NULL || (bn_ctx = BN_CTX_new()) == NULL)
        return NULL;

    if ((tmp = BN_new()) == NULL ||
        (tmp2 = BN_new()) == NULL ||
188
        (tmp3 = BN_new()) == NULL)
189 190 191 192
        goto err;

    if (!BN_mod_exp(tmp, g, x, N, bn_ctx))
        goto err;
193
    if ((k = srp_Calc_k(N, g)) == NULL)
194 195 196 197 198
        goto err;
    if (!BN_mod_mul(tmp2, tmp, k, N, bn_ctx))
        goto err;
    if (!BN_mod_sub(tmp, B, tmp2, N, bn_ctx))
        goto err;
C
Cynh 已提交
199
    if (!BN_mul(tmp3, u, x, bn_ctx))
200
        goto err;
C
Cynh 已提交
201
    if (!BN_add(tmp2, a, tmp3))
202
        goto err;
203 204 205 206 207
    K = BN_new();
    if (K != NULL && !BN_mod_exp(K, tmp, tmp2, N, bn_ctx)) {
        BN_free(K);
        K = NULL;
    }
208 209 210 211 212 213 214 215 216

 err:
    BN_CTX_free(bn_ctx);
    BN_clear_free(tmp);
    BN_clear_free(tmp2);
    BN_clear_free(tmp3);
    BN_free(k);
    return K;
}
B
Ben Laurie 已提交
217

M
Matt Caswell 已提交
218
int SRP_Verify_B_mod_N(const BIGNUM *B, const BIGNUM *N)
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237
{
    BIGNUM *r;
    BN_CTX *bn_ctx;
    int ret = 0;

    if (B == NULL || N == NULL || (bn_ctx = BN_CTX_new()) == NULL)
        return 0;

    if ((r = BN_new()) == NULL)
        goto err;
    /* Checks if B % N == 0 */
    if (!BN_nnmod(r, B, N, bn_ctx))
        goto err;
    ret = !BN_is_zero(r);
 err:
    BN_CTX_free(bn_ctx);
    BN_free(r);
    return ret;
}
B
Ben Laurie 已提交
238

M
Matt Caswell 已提交
239
int SRP_Verify_A_mod_N(const BIGNUM *A, const BIGNUM *N)
240 241 242 243 244
{
    /* Checks if A % N == 0 */
    return SRP_Verify_B_mod_N(A, N);
}

245
static SRP_gN knowngN[] = {
M
Matt Caswell 已提交
246 247 248 249 250 251 252
    {"8192", &bn_generator_19, &bn_group_8192},
    {"6144", &bn_generator_5, &bn_group_6144},
    {"4096", &bn_generator_5, &bn_group_4096},
    {"3072", &bn_generator_5, &bn_group_3072},
    {"2048", &bn_generator_2, &bn_group_2048},
    {"1536", &bn_generator_2, &bn_group_1536},
    {"1024", &bn_generator_2, &bn_group_1024},
253 254 255 256
};

# define KNOWN_GN_NUMBER sizeof(knowngN) / sizeof(SRP_gN)

257
/*
F
FdaSilvaYY 已提交
258
 * Check if G and N are known parameters. The values have been generated
259 260
 * from the ietf-tls-srp draft version 8
 */
M
Matt Caswell 已提交
261
char *SRP_check_known_gN_param(const BIGNUM *g, const BIGNUM *N)
262 263 264 265 266 267 268 269 270 271 272
{
    size_t i;
    if ((g == NULL) || (N == NULL))
        return 0;

    for (i = 0; i < KNOWN_GN_NUMBER; i++) {
        if (BN_cmp(knowngN[i].g, g) == 0 && BN_cmp(knowngN[i].N, N) == 0)
            return knowngN[i].id;
    }
    return NULL;
}
B
Ben Laurie 已提交
273

274
SRP_gN *SRP_get_default_gN(const char *id)
275 276 277 278 279 280 281 282 283 284 285
{
    size_t i;

    if (id == NULL)
        return knowngN;
    for (i = 0; i < KNOWN_GN_NUMBER; i++) {
        if (strcmp(knowngN[i].id, id) == 0)
            return knowngN + i;
    }
    return NULL;
}
B
Ben Laurie 已提交
286
#endif