aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/ffi
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/ffi')
-rw-r--r--src/lib/ffi/ffi.h93
-rw-r--r--src/lib/ffi/ffi_srp6.cpp125
2 files changed, 218 insertions, 0 deletions
diff --git a/src/lib/ffi/ffi.h b/src/lib/ffi/ffi.h
index 4dbc218c6..730ae4cfe 100644
--- a/src/lib/ffi/ffi.h
+++ b/src/lib/ffi/ffi.h
@@ -1782,6 +1782,99 @@ int botan_fpe_encrypt(botan_fpe_t fpe, botan_mp_t x, const uint8_t tweak[], size
BOTAN_PUBLIC_API(2,8)
int botan_fpe_decrypt(botan_fpe_t fpe, botan_mp_t x, const uint8_t tweak[], size_t tweak_len);
+/**
+* SRP-6 Server Session type
+*/
+typedef struct botan_srp6_server_session_struct* botan_srp6_server_session_t;
+
+/**
+* Initialize an SRP-6 server session object
+* @param srp6 SRP-6 server session object
+*/
+BOTAN_PUBLIC_API(3, 0)
+int botan_srp6_server_session_init(botan_srp6_server_session_t *srp6);
+
+/**
+* Frees all resources of the SRP-6 server session object
+* @param srp6 SRP-6 server session object
+* @return 0 if success, error if invalid object handle
+*/
+BOTAN_PUBLIC_API(3, 0)
+int botan_srp6_server_session_destroy(botan_srp6_server_session_t srp6);
+
+/**
+* SRP-6 Server side step 1
+* @param srp6 SRP-6 server session object
+* @param verifier the verification value saved from client registration
+* @param group_id the SRP group id
+* @param hash_id the SRP hash in use
+* @param rng_obj a random number generator object
+* @param B_pub out buffer to store the SRP-6 B value
+* @param B_pub_len SRP-6 B value length
+* @return 0 on success, negative on failure
+*/
+BOTAN_PUBLIC_API(3, 0)
+int botan_srp6_server_session_step1(botan_srp6_server_session_t srp6,
+ const uint8_t verifier[],
+ size_t verifier_len, const char *group_id,
+ const char *hash_id, botan_rng_t rng_obj,
+ uint8_t B_pub[], size_t *B_pub_len);
+
+/**
+* SRP-6 Server side step 2
+* @param srp6 SRP-6 server session object
+* @param A the client's value
+* @param A_len the client's value length
+* @param key out buffer to store the symmetric key value
+* @param key_len symmetric key length
+* @return 0 on success, negative on failure
+*/
+BOTAN_PUBLIC_API(3, 0)
+int botan_srp6_server_session_step2(botan_srp6_server_session_t srp6,
+ const uint8_t A[], size_t A_len,
+ uint8_t key[], size_t *key_len);
+
+/**
+* Generate a new SRP-6 verifier
+* @param identifier a username or other client identifier
+* @param password the secret used to authenticate user
+* @param salt a randomly chosen value, at least 128 bits long
+* @param group_id specifies the shared SRP group
+* @param hash_id specifies a secure hash function
+* @param verifier out buffer to store the SRP-6 verifier value
+* @param verifier_len SRP-6 verifier value length
+* @return 0 on success, negative on failure
+*/
+BOTAN_PUBLIC_API(3, 0)
+int botan_generate_srp6_verifier(const char *identifier, const char *password,
+ const uint8_t salt[], size_t salt_len,
+ const char *group_id, const char *hash_id,
+ uint8_t verifier[], size_t *verifier_len);
+
+/**
+* SRP6a Client side
+* @param username the username we are attempting login for
+* @param password the password we are attempting to use
+* @param group_id specifies the shared SRP group
+* @param hash_id specifies a secure hash function
+* @param salt is the salt value sent by the server
+* @param B is the server's public value
+* @param B_len is the server's public value length
+* @param rng_obj is a random number generator object
+* @param A out buffer to store the SRP-6 A value
+* @param A_len SRP-6 A verifier value length
+* @param K out buffer to store the symmetric value
+* @param K_len symmetric key length
+* @return 0 on success, negative on failure
+*/
+BOTAN_PUBLIC_API(3, 0)
+int botan_srp6_client_agree(const char *username, const char *password,
+ const char *group_id, const char *hash_id,
+ const uint8_t salt[], size_t salt_len,
+ const uint8_t B[], size_t B_len, botan_rng_t rng_obj,
+ uint8_t A[], size_t *A_len, uint8_t K[],
+ size_t *K_len);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/lib/ffi/ffi_srp6.cpp b/src/lib/ffi/ffi_srp6.cpp
new file mode 100644
index 000000000..7ae4d2204
--- /dev/null
+++ b/src/lib/ffi/ffi_srp6.cpp
@@ -0,0 +1,125 @@
+/*
+* (C) 2022 Rostyslav Khudolii
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include "botan/bigint.h"
+#include "botan/ffi.h"
+#include "botan/internal/ffi_rng.h"
+#include "botan/internal/ffi_util.h"
+#include "botan/rng.h"
+#include "botan/srp6.h"
+#include "botan/symkey.h"
+
+extern "C" {
+
+using namespace Botan_FFI;
+
+BOTAN_FFI_DECLARE_STRUCT(botan_srp6_server_session_struct,
+ Botan::SRP6_Server_Session, 0x44F7425F);
+
+int botan_srp6_server_session_init(botan_srp6_server_session_t *srp6) {
+return ffi_guard_thunk(__func__, [=]() -> int {
+*srp6 = new botan_srp6_server_session_struct(
+ std::make_unique<Botan::SRP6_Server_Session>());
+return BOTAN_FFI_SUCCESS;
+});
+}
+
+int botan_srp6_server_session_destroy(botan_srp6_server_session_t srp6) {
+return BOTAN_FFI_CHECKED_DELETE(srp6);
+}
+
+int botan_srp6_server_session_step1(botan_srp6_server_session_t srp6,
+ const uint8_t *verifier,
+ size_t verifier_len, const char *group_id,
+ const char *hash_id, botan_rng_t rng_obj,
+ uint8_t b_pub[], size_t *b_pub_len) {
+return BOTAN_FFI_DO(Botan::SRP6_Server_Session, srp6, s, {
+ if (!verifier || !group_id || !hash_id || !rng_obj) {
+ return BOTAN_FFI_ERROR_NULL_POINTER;
+ }
+ try {
+ Botan::RandomNumberGenerator &rng = safe_get(rng_obj);
+ auto v_bn = Botan::BigInt::decode(verifier, verifier_len);
+ auto b_pub_bn = s.step1(v_bn, group_id, hash_id, rng);
+ return write_vec_output(b_pub, b_pub_len,
+ Botan::BigInt::encode(b_pub_bn));
+ } catch (Botan::Decoding_Error &) {
+ return BOTAN_FFI_ERROR_BAD_PARAMETER;
+ } catch (Botan::Lookup_Error &) {
+ return BOTAN_FFI_ERROR_BAD_PARAMETER;
+ }
+ });
+}
+
+int botan_srp6_server_session_step2(botan_srp6_server_session_t srp6,
+ const uint8_t a[], size_t a_len,
+ uint8_t key[], size_t *key_len) {
+return BOTAN_FFI_DO(Botan::SRP6_Server_Session, srp6, s, {
+ if (!a) {
+ return BOTAN_FFI_ERROR_NULL_POINTER;
+ }
+ try {
+ Botan::BigInt a_bn = Botan::BigInt::decode(a, a_len);
+ auto key_sk = s.step2(a_bn);
+ return write_vec_output(key, key_len, key_sk.bits_of());
+ } catch (Botan::Decoding_Error &) {
+ return BOTAN_FFI_ERROR_BAD_PARAMETER;
+ }
+ });
+}
+
+int botan_generate_srp6_verifier(const char *username, const char *password,
+ const uint8_t salt[], size_t salt_len,
+ const char *group_id, const char *hash_id,
+ uint8_t verifier[], size_t *verifier_len) {
+return ffi_guard_thunk(__func__, [=]() -> int {
+if (!username || !password || !salt || !group_id || !hash_id) {
+return BOTAN_FFI_ERROR_NULL_POINTER;
+}
+try {
+std::vector<uint8_t> salt_vec(salt, salt + salt_len);
+auto verifier_bn = Botan::generate_srp6_verifier(
+ username, password, salt_vec, group_id, hash_id);
+return write_vec_output(verifier, verifier_len,
+ Botan::BigInt::encode(verifier_bn));
+} catch (Botan::Lookup_Error &) {
+return BOTAN_FFI_ERROR_BAD_PARAMETER;
+}
+});
+}
+
+int botan_srp6_client_agree(const char *identity, const char *password,
+ const char *group_id, const char *hash_id,
+ const uint8_t salt[], size_t salt_len,
+ const uint8_t b[], size_t b_len, botan_rng_t rng_obj,
+ uint8_t A[], size_t *A_len, uint8_t K[],
+ size_t *K_len) {
+return ffi_guard_thunk(__func__, [=]() -> int {
+if (!identity || !password || !salt || !group_id || !hash_id || !b || !rng_obj) {
+return BOTAN_FFI_ERROR_NULL_POINTER;
+}
+try {
+std::vector<uint8_t> saltv(salt, salt + salt_len);
+Botan::RandomNumberGenerator &rng = safe_get(rng_obj);
+auto b_bn = Botan::BigInt::decode(b, b_len);
+auto [A_bn, K_sk] = Botan::srp6_client_agree(
+ identity, password, group_id, hash_id, saltv, b_bn, rng);
+auto ret_a = write_vec_output(A, A_len, Botan::BigInt::encode(A_bn));
+auto ret_k = write_vec_output(K, K_len, K_sk.bits_of());
+if (ret_a != BOTAN_FFI_SUCCESS) {
+return ret_a;
+}
+if (ret_k != BOTAN_FFI_SUCCESS) {
+return ret_k;
+}
+return BOTAN_FFI_SUCCESS;
+} catch (Botan::Lookup_Error &) {
+return BOTAN_FFI_ERROR_BAD_PARAMETER;
+}
+});
+}
+
+}