1 /********************************************************************************************
2 * Supersingular Isogeny Key Encapsulation Library
3 *
4 * Abstract: supersingular isogeny key encapsulation (SIKE) protocol
5 *********************************************************************************************/
6 
7 #include <string.h>
8 #include "sikep434r3.h"
9 #include "sikep434r3_fips202.h"
10 #include "utils/s2n_safety.h"
11 #include "tls/s2n_kem.h"
12 #include "pq-crypto/s2n_pq.h"
13 #include "pq-crypto/s2n_pq_random.h"
14 #include "sikep434r3_fpx.h"
15 #include "sikep434r3_api.h"
16 
17 /* SIKE's key generation
18  * Outputs: secret key sk (S2N_SIKE_P434_R3_SECRET_KEY_BYTES = S2N_SIKE_P434_R3_MSG_BYTES + S2N_SIKE_P434_R3_SECRETKEY_B_BYTES + S2N_SIKE_P434_R3_PUBLIC_KEY_BYTES bytes)
19  *          public key pk (S2N_SIKE_P434_R3_PUBLIC_KEY_BYTES bytes) */
s2n_sike_p434_r3_crypto_kem_keypair(unsigned char * pk,unsigned char * sk)20 int s2n_sike_p434_r3_crypto_kem_keypair(unsigned char *pk, unsigned char *sk)
21 {
22     POSIX_ENSURE(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
23 
24     /* Generate lower portion of secret key sk <- s||SK */
25     POSIX_GUARD_RESULT(s2n_get_random_bytes(sk, S2N_SIKE_P434_R3_MSG_BYTES));
26     POSIX_GUARD(random_mod_order_B(sk + S2N_SIKE_P434_R3_MSG_BYTES));
27 
28     /* Generate public key pk */
29     EphemeralKeyGeneration_B(sk + S2N_SIKE_P434_R3_MSG_BYTES, pk);
30 
31     /* Append public key pk to secret key sk */
32     memcpy(&sk[S2N_SIKE_P434_R3_MSG_BYTES + S2N_SIKE_P434_R3_SECRETKEY_B_BYTES], pk, S2N_SIKE_P434_R3_PUBLIC_KEY_BYTES);
33 
34     return S2N_SUCCESS;
35 }
36 
37 /* SIKE's encapsulation
38  * Input:   public key pk         (S2N_SIKE_P434_R3_PUBLIC_KEY_BYTES bytes)
39  * Outputs: shared secret ss      (S2N_SIKE_P434_R3_SHARED_SECRET_BYTES bytes)
40  *          ciphertext message ct (S2N_SIKE_P434_R3_CIPHERTEXT_BYTES = S2N_SIKE_P434_R3_PUBLIC_KEY_BYTES + S2N_SIKE_P434_R3_MSG_BYTES bytes) */
s2n_sike_p434_r3_crypto_kem_enc(unsigned char * ct,unsigned char * ss,const unsigned char * pk)41 int s2n_sike_p434_r3_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk)
42 {
43     POSIX_ENSURE(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
44 
45     unsigned char ephemeralsk[S2N_SIKE_P434_R3_SECRETKEY_A_BYTES];
46     unsigned char jinvariant[S2N_SIKE_P434_R3_FP2_ENCODED_BYTES];
47     unsigned char h[S2N_SIKE_P434_R3_MSG_BYTES];
48     unsigned char temp[S2N_SIKE_P434_R3_CIPHERTEXT_BYTES+S2N_SIKE_P434_R3_MSG_BYTES];
49 
50     /* Generate ephemeralsk <- G(m||pk) mod oA */
51     POSIX_GUARD_RESULT(s2n_get_random_bytes(temp, S2N_SIKE_P434_R3_MSG_BYTES));
52     memcpy(&temp[S2N_SIKE_P434_R3_MSG_BYTES], pk, S2N_SIKE_P434_R3_PUBLIC_KEY_BYTES);
53     shake256(ephemeralsk, S2N_SIKE_P434_R3_SECRETKEY_A_BYTES, temp, S2N_SIKE_P434_R3_PUBLIC_KEY_BYTES+S2N_SIKE_P434_R3_MSG_BYTES);
54     ephemeralsk[S2N_SIKE_P434_R3_SECRETKEY_A_BYTES - 1] &= S2N_SIKE_P434_R3_MASK_ALICE;
55 
56     /* Encrypt */
57     EphemeralKeyGeneration_A(ephemeralsk, ct);
58     EphemeralSecretAgreement_A(ephemeralsk, pk, jinvariant);
59     shake256(h, S2N_SIKE_P434_R3_MSG_BYTES, jinvariant, S2N_SIKE_P434_R3_FP2_ENCODED_BYTES);
60     for (int i = 0; i < S2N_SIKE_P434_R3_MSG_BYTES; i++) {
61         ct[i + S2N_SIKE_P434_R3_PUBLIC_KEY_BYTES] = temp[i] ^ h[i];
62     }
63 
64     /* Generate shared secret ss <- H(m||ct) */
65     memcpy(&temp[S2N_SIKE_P434_R3_MSG_BYTES], ct, S2N_SIKE_P434_R3_CIPHERTEXT_BYTES);
66     shake256(ss, S2N_SIKE_P434_R3_SHARED_SECRET_BYTES, temp, S2N_SIKE_P434_R3_CIPHERTEXT_BYTES+S2N_SIKE_P434_R3_MSG_BYTES);
67 
68     return S2N_SUCCESS;
69 }
70 
71 /* SIKE's decapsulation
72  * Input:   secret key sk         (S2N_SIKE_P434_R3_SECRET_KEY_BYTES = S2N_SIKE_P434_R3_MSG_BYTES + S2N_SIKE_P434_R3_SECRETKEY_B_BYTES + S2N_SIKE_P434_R3_PUBLIC_KEY_BYTES bytes)
73  *          ciphertext message ct (S2N_SIKE_P434_R3_CIPHERTEXT_BYTES = S2N_SIKE_P434_R3_PUBLIC_KEY_BYTES + S2N_SIKE_P434_R3_MSG_BYTES bytes)
74  * Outputs: shared secret ss      (S2N_SIKE_P434_R3_SHARED_SECRET_BYTES bytes) */
s2n_sike_p434_r3_crypto_kem_dec(unsigned char * ss,const unsigned char * ct,const unsigned char * sk)75 int s2n_sike_p434_r3_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk)
76 {
77     POSIX_ENSURE(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
78 
79     unsigned char ephemeralsk_[S2N_SIKE_P434_R3_SECRETKEY_A_BYTES];
80     unsigned char jinvariant_[S2N_SIKE_P434_R3_FP2_ENCODED_BYTES];
81     unsigned char h_[S2N_SIKE_P434_R3_MSG_BYTES];
82     unsigned char c0_[S2N_SIKE_P434_R3_PUBLIC_KEY_BYTES];
83     unsigned char temp[S2N_SIKE_P434_R3_CIPHERTEXT_BYTES+S2N_SIKE_P434_R3_MSG_BYTES];
84 
85     /* Decrypt */
86     EphemeralSecretAgreement_B(sk + S2N_SIKE_P434_R3_MSG_BYTES, ct, jinvariant_);
87     shake256(h_, S2N_SIKE_P434_R3_MSG_BYTES, jinvariant_, S2N_SIKE_P434_R3_FP2_ENCODED_BYTES);
88     for (int i = 0; i < S2N_SIKE_P434_R3_MSG_BYTES; i++) {
89         temp[i] = ct[i + S2N_SIKE_P434_R3_PUBLIC_KEY_BYTES] ^ h_[i];
90     }
91 
92     /* Generate ephemeralsk_ <- G(m||pk) mod oA */
93     memcpy(&temp[S2N_SIKE_P434_R3_MSG_BYTES], &sk[S2N_SIKE_P434_R3_MSG_BYTES + S2N_SIKE_P434_R3_SECRETKEY_B_BYTES], S2N_SIKE_P434_R3_PUBLIC_KEY_BYTES);
94     shake256(ephemeralsk_, S2N_SIKE_P434_R3_SECRETKEY_A_BYTES, temp, S2N_SIKE_P434_R3_PUBLIC_KEY_BYTES+S2N_SIKE_P434_R3_MSG_BYTES);
95     ephemeralsk_[S2N_SIKE_P434_R3_SECRETKEY_A_BYTES - 1] &= S2N_SIKE_P434_R3_MASK_ALICE;
96 
97     /* Generate shared secret ss <- H(m||ct), or output ss <- H(s||ct) in case of ct verification failure */
98     EphemeralKeyGeneration_A(ephemeralsk_, c0_);
99 
100     /* Verify ciphertext.
101      * If c0_ and ct are NOT equal, decaps failed and we overwrite the shared secret
102      * with pseudorandom noise (ss = H(s||ct)) by performing the copy (dont_copy = false).
103      *
104      * If c0_ and ct are equal, then decaps succeeded and we skip the overwrite and output
105      * the actual shared secret: ss = H(m||ct) (dont_copy = true). */
106     bool dont_copy = s2n_constant_time_equals(c0_, ct, S2N_SIKE_P434_R3_PUBLIC_KEY_BYTES);
107     POSIX_GUARD(s2n_constant_time_copy_or_dont(temp, sk, S2N_SIKE_P434_R3_MSG_BYTES, dont_copy));
108     memcpy(&temp[S2N_SIKE_P434_R3_MSG_BYTES], ct, S2N_SIKE_P434_R3_CIPHERTEXT_BYTES);
109     shake256(ss, S2N_SIKE_P434_R3_SHARED_SECRET_BYTES, temp, S2N_SIKE_P434_R3_CIPHERTEXT_BYTES+S2N_SIKE_P434_R3_MSG_BYTES);
110 
111     return S2N_SUCCESS;
112 }
113