1 /* srp.h
2  *
3  * Copyright (C) 2006-2021 wolfSSL Inc.
4  *
5  * This file is part of wolfSSL.
6  *
7  * wolfSSL is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * wolfSSL is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20  */
21 
22 /*!
23     \file wolfssl/wolfcrypt/srp.h
24 */
25 
26 #ifdef WOLFCRYPT_HAVE_SRP
27 
28 #ifndef WOLFCRYPT_SRP_H
29 #define WOLFCRYPT_SRP_H
30 
31 #include <wolfssl/wolfcrypt/types.h>
32 #include <wolfssl/wolfcrypt/sha.h>
33 #include <wolfssl/wolfcrypt/sha256.h>
34 #include <wolfssl/wolfcrypt/sha512.h>
35 #include <wolfssl/wolfcrypt/integer.h>
36 
37 #ifdef __cplusplus
38     extern "C" {
39 #endif
40 
41 /* Select the largest available hash for the buffer size. */
42 #if defined(WOLFSSL_SHA512)
43     #define SRP_MAX_DIGEST_SIZE WC_SHA512_DIGEST_SIZE
44 #elif defined(WOLFSSL_SHA384)
45     #define SRP_MAX_DIGEST_SIZE WC_SHA384_DIGEST_SIZE
46 #elif !defined(NO_SHA256)
47     #define SRP_MAX_DIGEST_SIZE WC_SHA256_DIGEST_SIZE
48 #elif !defined(NO_SHA)
49     #define SRP_MAX_DIGEST_SIZE WC_SHA_DIGEST_SIZE
50 #else
51     #error "You have to have some kind of SHA hash if you want to use SRP."
52 #endif
53 
54 /* Set the minimum number of bits acceptable in an SRP modulus */
55 #define SRP_MODULUS_MIN_BITS 512
56 
57 /* Set the minimum number of bits acceptable for private keys (RFC 5054) */
58 #define SRP_PRIVATE_KEY_MIN_BITS 256
59 
60 /* salt size for SRP password */
61 #define SRP_SALT_SIZE  16
62 
63 /**
64  * SRP side, client or server.
65  */
66 typedef enum {
67     SRP_CLIENT_SIDE  = 0,
68     SRP_SERVER_SIDE  = 1,
69 } SrpSide;
70 
71 /**
72  * SRP hash type, SHA[1|256|384|512].
73  */
74 typedef enum {
75         SRP_TYPE_SHA    = 1,
76         SRP_TYPE_SHA256 = 2,
77         SRP_TYPE_SHA384 = 3,
78         SRP_TYPE_SHA512 = 4,
79 } SrpType;
80 
81 
82 /**
83  * SRP hash struct.
84  */
85 typedef struct {
86     byte type;
87     union {
88         #ifndef NO_SHA
89             wc_Sha sha;
90         #endif
91         #ifndef NO_SHA256
92             wc_Sha256 sha256;
93         #endif
94         #ifdef WOLFSSL_SHA384
95             wc_Sha384 sha384;
96         #endif
97         #ifdef WOLFSSL_SHA512
98             wc_Sha512 sha512;
99         #endif
100     } data;
101 } SrpHash;
102 
103 typedef struct Srp {
104     SrpSide side;                   /**< Client or Server, @see SrpSide.      */
105     SrpType type;                   /**< Hash type, @see SrpType.             */
106     byte*   user;                   /**< Username, login.                     */
107     word32  userSz;                 /**< Username length.                     */
108     byte*   salt;                   /**< Small salt.                          */
109     word32  saltSz;                 /**< Salt length.                         */
110     mp_int  N;                      /**< Modulus. N = 2q+1, [q, N] are primes.*/
111     mp_int  g;                      /**< Generator. A generator modulo N.     */
112     byte    k[SRP_MAX_DIGEST_SIZE]; /**< Multiplier parameter. k = H(N, g)   */
113     mp_int  auth;                   /**< Client: x = H(salt + H(user:pswd))   */
114                                     /**< Server: v = g ^ x % N                */
115     mp_int  priv;                   /**< Private ephemeral value.             */
116     SrpHash client_proof;           /**< Client proof. Sent to the Server.    */
117     SrpHash server_proof;           /**< Server proof. Sent to the Client.    */
118     byte*   key;                    /**< Session key.                         */
119     word32  keySz;                  /**< Session key length.                  */
120     int (*keyGenFunc_cb) (struct Srp* srp, byte* secret, word32 size);
121         /**< Function responsible for generating the session key.             */
122         /**< It MUST use XMALLOC with type DYNAMIC_TYPE_SRP to allocate the   */
123         /**< key buffer for this structure and set keySz to the buffer size.  */
124         /**< The default function used by this implementation is a modified   */
125         /**< version of t_mgf1 that uses the proper hash function according   */
126         /**< to srp->type.                                                    */
127     void*   heap;                   /**< heap hint pointer                    */
128 } Srp;
129 
130 /**
131  * Initializes the Srp struct for usage.
132  *
133  * @param[out] srp   the Srp structure to be initialized.
134  * @param[in]  type  the hash type to be used.
135  * @param[in]  side  the side of the communication.
136  *
137  * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h
138  */
139 WOLFSSL_API int wc_SrpInit(Srp* srp, SrpType type, SrpSide side);
140 WOLFSSL_API int wc_SrpInit_ex(Srp* srp, SrpType type, SrpSide side,
141     void* heap, int devId);
142 
143 /**
144  * Releases the Srp struct resources after usage.
145  *
146  * @param[in,out] srp    the Srp structure to be terminated.
147  */
148 WOLFSSL_API void wc_SrpTerm(Srp* srp);
149 
150 /**
151  * Sets the username.
152  *
153  * This function MUST be called after wc_SrpInit.
154  *
155  * @param[in,out] srp       the Srp structure.
156  * @param[in]     username  the buffer containing the username.
157  * @param[in]     size      the username size in bytes
158  *
159  * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h
160  */
161 WOLFSSL_API int wc_SrpSetUsername(Srp* srp, const byte* username, word32 size);
162 
163 
164 /**
165  * Sets the srp parameters based on the username.
166  *
167  * This function MUST be called after wc_SrpSetUsername.
168  *
169  * @param[in,out] srp       the Srp structure.
170  * @param[in]     N         the Modulus. N = 2q+1, [q, N] are primes.
171  * @param[in]     nSz       the N size in bytes.
172  * @param[in]     g         the Generator modulo N.
173  * @param[in]     gSz       the g size in bytes
174  * @param[in]     salt      a small random salt. Specific for each username.
175  * @param[in]     saltSz    the salt size in bytes
176  *
177  * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h
178  */
179 WOLFSSL_API int wc_SrpSetParams(Srp* srp, const byte* N,    word32 nSz,
180                                           const byte* g,    word32 gSz,
181                                           const byte* salt, word32 saltSz);
182 
183 /**
184  * Sets the password.
185  *
186  * Setting the password does not persists the clear password data in the
187  * srp structure. The client calculates x = H(salt + H(user:pswd)) and stores
188  * it in the auth field.
189  *
190  * This function MUST be called after wc_SrpSetParams and is CLIENT SIDE ONLY.
191  *
192  * @param[in,out] srp       the Srp structure.
193  * @param[in]     password  the buffer containing the password.
194  * @param[in]     size      the password size in bytes.
195  *
196  * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h
197  */
198 WOLFSSL_API int wc_SrpSetPassword(Srp* srp, const byte* password, word32 size);
199 
200 /**
201  * Sets the verifier.
202  *
203  * This function MUST be called after wc_SrpSetParams and is SERVER SIDE ONLY.
204  *
205  * @param[in,out] srp       the Srp structure.
206  * @param[in]     verifier  the buffer containing the verifier.
207  * @param[in]     size      the verifier size in bytes.
208  *
209  * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h
210  */
211 WOLFSSL_API int wc_SrpSetVerifier(Srp* srp, const byte* verifier, word32 size);
212 
213 /**
214  * Gets the verifier.
215  *
216  * The client calculates the verifier with v = g ^ x % N.
217  * This function MAY be called after wc_SrpSetPassword and is CLIENT SIDE ONLY.
218  *
219  * @param[in,out] srp       the Srp structure.
220  * @param[out]    verifier  the buffer to write the verifier.
221  * @param[in,out] size      the buffer size in bytes. Will be updated with the
222  *                          verifier size.
223  *
224  * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h
225  */
226 WOLFSSL_API int wc_SrpGetVerifier(Srp* srp, byte* verifier, word32* size);
227 
228 /**
229  * Sets the private ephemeral value.
230  *
231  * The private ephemeral value is known as:
232  *   a at the client side. a = random()
233  *   b at the server side. b = random()
234  * This function is handy for unit test cases or if the developer wants to use
235  * an external random source to set the ephemeral value.
236  * This function MAY be called before wc_SrpGetPublic.
237  *
238  * @param[in,out] srp       the Srp structure.
239  * @param[in]     priv      the ephemeral value.
240  * @param[in]     size      the private size in bytes.
241  *
242  * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h
243  */
244 WOLFSSL_API int wc_SrpSetPrivate(Srp* srp, const byte* priv, word32 size);
245 
246 /**
247  * Gets the public ephemeral value.
248  *
249  * The public ephemeral value is known as:
250  *   A at the client side. A = g ^ a % N
251  *   B at the server side. B = (k * v + (g ^ b % N)) % N
252  * This function MUST be called after wc_SrpSetPassword or wc_SrpSetVerifier.
253  *
254  * @param[in,out] srp       the Srp structure.
255  * @param[out]    pub       the buffer to write the public ephemeral value.
256  * @param[in,out] size      the the buffer size in bytes. Will be updated with
257  *                          the ephemeral value size.
258  *
259  * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h
260  */
261 WOLFSSL_API int wc_SrpGetPublic(Srp* srp, byte* pub, word32* size);
262 
263 
264 /**
265  * Computes the session key.
266  *
267  * The key can be accessed at srp->key after success.
268  *
269  * @param[in,out] srp               the Srp structure.
270  * @param[in]     clientPubKey      the client's public ephemeral value.
271  * @param[in]     clientPubKeySz    the client's public ephemeral value size.
272  * @param[in]     serverPubKey      the server's public ephemeral value.
273  * @param[in]     serverPubKeySz    the server's public ephemeral value size.
274  *
275  * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h
276  */
277 WOLFSSL_API int wc_SrpComputeKey(Srp* srp,
278                                  byte* clientPubKey, word32 clientPubKeySz,
279                                  byte* serverPubKey, word32 serverPubKeySz);
280 
281 /**
282  * Gets the proof.
283  *
284  * This function MUST be called after wc_SrpComputeKey.
285  *
286  * @param[in,out] srp   the Srp structure.
287  * @param[out]    proof the buffer to write the proof.
288  * @param[in,out] size  the buffer size in bytes. Will be updated with the
289  *                          proof size.
290  *
291  * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h
292  */
293 WOLFSSL_API int wc_SrpGetProof(Srp* srp, byte* proof, word32* size);
294 
295 /**
296  * Verifies the peers proof.
297  *
298  * This function MUST be called before wc_SrpGetSessionKey.
299  *
300  * @param[in,out] srp   the Srp structure.
301  * @param[in]     proof the peers proof.
302  * @param[in]     size  the proof size in bytes.
303  *
304  * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h
305  */
306 WOLFSSL_API int wc_SrpVerifyPeersProof(Srp* srp, byte* proof, word32 size);
307 
308 #ifdef __cplusplus
309    } /* extern "C" */
310 #endif
311 
312 #endif /* WOLFCRYPT_SRP_H */
313 #endif /* WOLFCRYPT_HAVE_SRP */
314