]> git.codecow.com Git - Monocypher.git/commitdiff
reworked API, more tests
authorLoup Vaillant <loup@loup-vaillant.fr>
Wed, 22 Feb 2017 13:02:11 +0000 (14:02 +0100)
committerLoup Vaillant <loup@loup-vaillant.fr>
Wed, 22 Feb 2017 13:02:11 +0000 (14:02 +0100)
monocypher.c
monocypher.h
test.c
vectors_x25519

index 0d1fdf6c65951270ee5a40d01ab42712ac0309fa..722ad0a341575caa7831c8cb4d7a47a9c4a32397 100644 (file)
@@ -80,7 +80,14 @@ int crypto_memcmp(const u8 *p1, const u8 *p2, size_t n)
 {
     unsigned diff = 0;
     FOR (i, 0, n) { diff |= (p1[i] ^ p2[i]); }
-    return diff;
+    return (1 & ((diff - 1) >> 8)) - 1;
+}
+
+int crypto_zerocmp(const u8 *p, size_t n)
+{
+    unsigned diff = 0;
+    FOR (i, 0, n) { diff |= p[i]; }
+    return (1 & ((diff - 1) >> 8)) - 1;
 }
 
 /////////////////
@@ -159,8 +166,8 @@ void crypto_chacha20_Xinit(crypto_chacha_ctx *ctx,
 }
 
 void crypto_chacha20_encrypt(crypto_chacha_ctx *ctx,
-                             const u8          *plain_text,
                              u8                *cipher_text,
+                             const u8          *plain_text,
                              size_t             message_size)
 {
     FOR (i, 0, message_size) {
@@ -190,7 +197,7 @@ void crypto_chacha20_stream(crypto_chacha_ctx *ctx,
                             u8                *cipher_text,
                             size_t             message_size)
 {
-    crypto_chacha20_encrypt(ctx, 0, cipher_text, message_size);
+    crypto_chacha20_encrypt(ctx, cipher_text, 0, message_size);
 }
 
 
@@ -676,14 +683,12 @@ static u32 gidx_next(gidx_ctx *ctx)
 }
 
 // Main algorithm
-void crypto_argon2i(u8       *tag,      u32 tag_size,
-                    const u8 *password, u32 password_size,
-                    const u8 *salt,     u32 salt_size,
-                    const u8 *key,      u32 key_size,
-                    const u8 *ad,       u32 ad_size,
-                    void *work_area,
-                    u32 nb_blocks,
-                    u32 nb_iterations)
+void crypto_argon2i(u8       *tag,       u32 tag_size,
+                    void     *work_area, u32 nb_blocks, u32 nb_iterations,
+                    const u8 *password,  u32 password_size,
+                    const u8 *salt,      u32 salt_size,
+                    const u8 *key,       u32 key_size,
+                    const u8 *ad,        u32 ad_size)
 {
     // work area seen as blocks (must be suitably aligned)
     block *blocks = (block*)work_area;
@@ -938,10 +943,9 @@ static int fe_isnegative(const fe f)
 
 static int fe_isnonzero(const fe f)
 {
-    static const u8 zero[32] = {0};
     u8 s[32];
     fe_tobytes(s, f);
-    return crypto_memcmp(s, zero, 32);
+    return crypto_zerocmp(s, 32);
 }
 
 ///////////////
@@ -955,9 +959,9 @@ sv trim_scalar(u8 s[32])
     s[31] |= 64;
 }
 
-void crypto_x25519(u8       shared_secret   [32],
-                   const u8 your_secret_key [32],
-                   const u8 their_public_key[32])
+int crypto_x25519(u8       shared_secret   [32],
+                  const u8 your_secret_key [32],
+                  const u8 their_public_key[32])
 {
     // computes the scalar product
     fe x1, x2, z2, x3, z3;
@@ -999,6 +1003,10 @@ void crypto_x25519(u8       shared_secret   [32],
     fe_invert(z2, z2);
     fe_mul(x2, x2, z2);
     fe_tobytes(shared_secret, x2);
+
+    // Returns -1 if the input is all zero
+    // (happens with some malicious public keys)
+    return -1 - crypto_zerocmp(shared_secret, 32);
 }
 
 void crypto_x25519_public_key(u8       public_key[32],
@@ -1280,14 +1288,15 @@ int crypto_check(const u8  signature[64],
 ////////////////////
 /// Key exchange ///
 ////////////////////
-void crypto_key_exchange(u8       shared_key[32],
-                         const u8 your_secret_key [32],
-                         const u8 their_public_key[32])
+int crypto_key_exchange(u8       shared_key[32],
+                        const u8 your_secret_key [32],
+                        const u8 their_public_key[32])
 {
     static const u8 zero[16] = {0};
     u8 shared_secret[32];
-    crypto_x25519(shared_secret, your_secret_key, their_public_key);
+    int status = crypto_x25519(shared_secret, your_secret_key, their_public_key);
     crypto_chacha20_H(shared_key, shared_secret, zero);
+    return status;
 }
 
 ////////////////////////////////
@@ -1315,7 +1324,7 @@ void crypto_aead_lock(u8        mac[16],
     crypto_chacha_ctx e_ctx;
     crypto_chacha20_Xinit  (&e_ctx, key, nonce);
     crypto_chacha20_stream (&e_ctx, auth_key, 32);
-    crypto_chacha20_encrypt(&e_ctx, plaintext, ciphertext, text_size);
+    crypto_chacha20_encrypt(&e_ctx, ciphertext, plaintext, text_size);
     authenticate2(mac, auth_key, ad, ad_size, ciphertext, text_size);
 }
 
@@ -1332,7 +1341,7 @@ int crypto_aead_unlock(u8       *plaintext,
     crypto_chacha20_stream(&e_ctx, auth_key, 32);
     authenticate2(real_mac, auth_key, ad, ad_size, ciphertext, text_size);
     if (crypto_memcmp(real_mac, mac, 16)) return -1;  // reject forgeries
-    crypto_chacha20_encrypt(&e_ctx, ciphertext, plaintext, text_size);
+    crypto_chacha20_encrypt(&e_ctx, plaintext, ciphertext, text_size);
     return 0;
 }
 
index 1f8e6eda2b1f26575de55c4fb82c3fdd3ec77262..2bb78ff9d589e352bf1ef8febe6e835d83f80b2d 100644 (file)
@@ -5,9 +5,13 @@
 #include <stddef.h>
 
 // Constant time equality verification
-// returns 0 if it matches, something else otherwise.
+// returns 0 if it matches, -1 otherwise.
 int crypto_memcmp(const uint8_t *p1, const uint8_t *p2, size_t n);
 
+// constant time zero comparison.
+// returns 0 if the input is all zero, -1 otherwise.
+int crypto_zerocmp(const uint8_t *p, size_t n);
+
 ////////////////
 /// Chacha20 ///
 ////////////////
@@ -30,8 +34,8 @@ void crypto_chacha20_Xinit(crypto_chacha_ctx *ctx,
                            const uint8_t      nonce[24]);
 
 void crypto_chacha20_encrypt(crypto_chacha_ctx *ctx,
-                             const uint8_t     *plain_text,
                              uint8_t           *cipher_text,
+                             const uint8_t     *plain_text,
                              size_t             message_size);
 
 void crypto_chacha20_stream(crypto_chacha_ctx *ctx,
@@ -91,20 +95,19 @@ void crypto_blake2b(uint8_t out[64], const uint8_t *in, size_t inlen);
 /// Argon2 i ///
 ////////////////
 void crypto_argon2i(uint8_t       *tag,       uint32_t tag_size,      // >= 4
+                    void          *work_area, uint32_t nb_blocks,     // >= 8
+                    uint32_t       nb_iterations,
                     const uint8_t *password,  uint32_t password_size,
                     const uint8_t *salt,      uint32_t salt_size,     // >= 8
                     const uint8_t *key,       uint32_t key_size,
-                    const uint8_t *ad,        uint32_t ad_size,
-                    void    *work_area,
-                    uint32_t nb_blocks,                               // >= 8
-                    uint32_t nb_iterations);
+                    const uint8_t *ad,        uint32_t ad_size);
 
 ///////////////
 /// X-25519 ///
 ///////////////
-void crypto_x25519(uint8_t       shared_secret   [32],
-                   const uint8_t your_secret_key [32],
-                   const uint8_t their_public_key[32]);
+int crypto_x25519(uint8_t       shared_secret   [32],
+                  const uint8_t your_secret_key [32],
+                  const uint8_t their_public_key[32]);
 
 void crypto_x25519_public_key(uint8_t       public_key[32],
                               const uint8_t secret_key[32]);
@@ -128,9 +131,9 @@ int crypto_check(const uint8_t  signature[64],
 ////////////////////
 /// Key exchange ///
 ////////////////////
-void crypto_key_exchange(uint8_t       shared_key      [32],
-                         const uint8_t your_secret_key [32],
-                         const uint8_t their_public_key[32]);
+int crypto_key_exchange(uint8_t       shared_key      [32],
+                        const uint8_t your_secret_key [32],
+                        const uint8_t their_public_key[32]);
 
 ////////////////////////////////
 /// Authenticated encryption ///
diff --git a/test.c b/test.c
index b7e5437dac675b33eb5046e466bf051340610524..357d49272b695a60ee18f4cf5b1252f8a3c1ae5d 100644 (file)
--- a/test.c
+++ b/test.c
@@ -86,7 +86,7 @@ sv stream_drop(stream *s)
 /// Vector of octets ///
 ////////////////////////
 typedef struct {
-    uint8_t *buf;
+    u8 *buf;
     size_t   buf_size;
     size_t   size;
 } vector;
@@ -94,7 +94,7 @@ typedef struct {
 static vector vec_new(size_t buf_size)
 {
     vector v;
-    v.buf      = (uint8_t*)alloc(buf_size);
+    v.buf      = (u8*)alloc(buf_size);
     v.buf_size = buf_size;
     v.size     = 0;
     return v;
@@ -112,12 +112,12 @@ sv vec_del(vector *v)
     free(v->buf);
 }
 
-sv vec_push_back(vector *v, uint8_t e)
+sv vec_push_back(vector *v, u8 e)
 {
     if (v->buf_size == v->size) {
         // double initial buffer size (and then some)
         size_t   new_buf_size = v->buf_size * 2 + 1;
-        uint8_t *new_buf   = (uint8_t*)alloc(new_buf_size);
+        u8 *new_buf   = (u8*)alloc(new_buf_size);
         memcpy(new_buf, v->buf, v->buf_size);
         free(v->buf);
         v->buf   = new_buf;
@@ -151,8 +151,8 @@ static vector read_hex_line(stream *s)
     vector v = vec_new(64);
     next_number(s);
     while (stream_peek(s) != ':') {
-        uint8_t msb = uint_of_char(stream_get(s));
-        uint8_t lsb = uint_of_char(stream_get(s));
+        u8 msb = uint_of_char(stream_get(s));
+        u8 lsb = uint_of_char(stream_get(s));
         vec_push_back(&v, lsb | (msb << 4));
     }
     stream_drop(s);
@@ -283,14 +283,12 @@ sv argon2i(const vector in[], vector *out)
         const vector *key           = in + 4;
         const vector *ad            = in + 5;
         void         *work_area     = alloc(nb_blocks->buf[0] * 1024);
-        crypto_argon2i(out     ->buf, out     ->size,
-                       password->buf, password->size,
-                       salt    ->buf, salt    ->size,
-                       key     ->buf, key     ->size,
-                       ad      ->buf, ad      ->size,
-                       work_area,
-                       nb_blocks    ->buf[0],
-                       nb_iterations->buf[0]);
+        crypto_argon2i(out     ->buf, out      ->size,
+                       work_area    , nb_blocks->buf[0], nb_iterations->buf[0],
+                       password->buf, password ->size,
+                       salt    ->buf, salt     ->size,
+                       key     ->buf, key      ->size,
+                       ad      ->buf, ad       ->size);
         free(work_area);
 }
 
@@ -298,12 +296,15 @@ sv x25519(const vector in[], vector *out)
 {
     const vector *scalar = in;
     const vector *point  = in + 1;
-    crypto_x25519(out->buf, scalar->buf, point->buf);
+    int report   = crypto_x25519(out->buf, scalar->buf, point->buf);
+    int not_zero = crypto_zerocmp(out->buf, out->size);
+    if ( not_zero &&  report)  printf("FAILURE: x25519 false all_zero report\n");
+    if (!not_zero && !report)  printf("FAILURE: x25519 failed to report zero\n");
 }
 
-sv iterate_x25519(uint8_t k[32], uint8_t u[32])
+sv iterate_x25519(u8 k[32], u8 u[32])
 {
-    uint8_t tmp[32];
+    u8 tmp[32];
     crypto_x25519(tmp , k, u);
     memcpy(u, k  , 32);
     memcpy(k, tmp, 32);
@@ -311,31 +312,31 @@ sv iterate_x25519(uint8_t k[32], uint8_t u[32])
 
 static int test_x25519()
 {
-    uint8_t _1   [32] = {0x42, 0x2c, 0x8e, 0x7a, 0x62, 0x27, 0xd7, 0xbc,
-                         0xa1, 0x35, 0x0b, 0x3e, 0x2b, 0xb7, 0x27, 0x9f,
-                         0x78, 0x97, 0xb8, 0x7b, 0xb6, 0x85, 0x4b, 0x78,
-                         0x3c, 0x60, 0xe8, 0x03, 0x11, 0xae, 0x30, 0x79};
-    uint8_t k[32] = {9};
-    uint8_t u[32] = {9};
+    u8 _1   [32] = {0x42, 0x2c, 0x8e, 0x7a, 0x62, 0x27, 0xd7, 0xbc,
+                    0xa1, 0x35, 0x0b, 0x3e, 0x2b, 0xb7, 0x27, 0x9f,
+                    0x78, 0x97, 0xb8, 0x7b, 0xb6, 0x85, 0x4b, 0x78,
+                    0x3c, 0x60, 0xe8, 0x03, 0x11, 0xae, 0x30, 0x79};
+    u8 k[32] = {9};
+    u8 u[32] = {9};
 
     crypto_x25519_public_key(k, u);
     int status = crypto_memcmp(k, _1, 32);
     printf("%s: x25519 1\n", status != 0 ? "FAILED" : "OK");
 
-    uint8_t _1k  [32] = {0x68, 0x4c, 0xf5, 0x9b, 0xa8, 0x33, 0x09, 0x55,
-                         0x28, 0x00, 0xef, 0x56, 0x6f, 0x2f, 0x4d, 0x3c,
-                         0x1c, 0x38, 0x87, 0xc4, 0x93, 0x60, 0xe3, 0x87,
-                         0x5f, 0x2e, 0xb9, 0x4d, 0x99, 0x53, 0x2c, 0x51};
+    u8 _1k  [32] = {0x68, 0x4c, 0xf5, 0x9b, 0xa8, 0x33, 0x09, 0x55,
+                    0x28, 0x00, 0xef, 0x56, 0x6f, 0x2f, 0x4d, 0x3c,
+                    0x1c, 0x38, 0x87, 0xc4, 0x93, 0x60, 0xe3, 0x87,
+                    0x5f, 0x2e, 0xb9, 0x4d, 0x99, 0x53, 0x2c, 0x51};
     FOR (i, 1, 1000) { iterate_x25519(k, u); }
     status |= crypto_memcmp(k, _1k, 32);
     printf("%s: x25519 1K\n", status != 0 ? "FAILED" : "OK");
 
     // too long; didn't run
-    //uint8_t _100k[32] = {0x7c, 0x39, 0x11, 0xe0, 0xab, 0x25, 0x86, 0xfd,
-    //                     0x86, 0x44, 0x97, 0x29, 0x7e, 0x57, 0x5e, 0x6f,
-    //                     0x3b, 0xc6, 0x01, 0xc0, 0x88, 0x3c, 0x30, 0xdf,
-    //                     0x5f, 0x4d, 0xd2, 0xd2, 0x4f, 0x66, 0x54, 0x24};
-    // FOR (i, 1000, 1000000) { iterate_x25519(k, u); }
+    //u8 _100k[32] = {0x7c, 0x39, 0x11, 0xe0, 0xab, 0x25, 0x86, 0xfd,
+    //                0x86, 0x44, 0x97, 0x29, 0x7e, 0x57, 0x5e, 0x6f,
+    //                0x3b, 0xc6, 0x01, 0xc0, 0x88, 0x3c, 0x30, 0xdf,
+    //                0x5f, 0x4d, 0xd2, 0xd2, 0x4f, 0x66, 0x54, 0x24};
+    //FOR (i, 1000, 1000000) { iterate_x25519(k, u); }
     //status |= crypto_memcmp(k, _100k, 32);
     //printf("%s: x25519 1M\n", status != 0 ? "FAILED" : "OK");
     return status;
@@ -372,8 +373,8 @@ sv ed25519_sign2(const vector in[], vector *out)
         printf("FAILURE: signature check failed to recognise signature\n");
     }
     // test forgery rejections
-    uint8_t fake_signature1[64];
-    uint8_t fake_signature2[64];
+    u8 fake_signature1[64];
+    u8 fake_signature2[64];
     FOR (i, 0, 64) {
         fake_signature1[i] = out->buf[i] + 1;
         fake_signature2[i] = out->buf[i] + 1;
@@ -389,33 +390,40 @@ sv key_exchange(const vector in[], vector *out)
     const vector *secret_key = in;
     const vector *public_key = in + 1;
     crypto_key_exchange(out->buf, secret_key->buf, public_key->buf);
-
 }
 
 static int test_aead()
 {
-    uint8_t key[32]      = { 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
-                             0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7 };
-    uint8_t nonce[24]    = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-                             1, 1, 1, 1, 1, 1, 1, 1 };
-    uint8_t ad       [4] = { 3, 2, 1, 0 };
-    uint8_t plaintext[8] = { 7, 6, 5, 4, 3, 2, 1, 0 };
-    uint8_t box[24];
-    uint8_t out[8];
+    u8 key[32]      = { 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
+                        0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7 };
+    u8 nonce[24]    = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                        1, 1, 1, 1, 1, 1, 1, 1 };
+    u8 ad       [4] = { 3, 2, 1, 0 };
+    u8 plaintext[8] = { 7, 6, 5, 4, 3, 2, 1, 0 };
+    u8 box[24], box2[24];
+    u8 out[8];
     int status = 0;
-    crypto_lock(box, key, nonce, plaintext, 8);           // make true message
-    status |= crypto_unlock(out, key, nonce, box, 8+16);  // accept true message
-    status |= crypto_memcmp(plaintext, out, 8);           // roundtrip
-    box[0]++;                                             // make forgery
-    status |= !crypto_unlock(out, key, nonce, box, 8+16); // reject forgery
-    printf("%s: aead\n", status != 0 ? "FAILED" : "OK");
-
+    // AEAD roundtrip
     crypto_aead_lock(box, box+16, key, nonce, ad, 4, plaintext, 8);
     status |= crypto_aead_unlock(out, key, nonce, box, ad, 4, box+16, 8);
     status |= crypto_memcmp(plaintext, out, 8);
     box[0]++;
     status |= !crypto_aead_unlock(out, key, nonce, box, ad, 4, box+16, 8);
+    printf("%s: aead (detached)\n", status != 0 ? "FAILED" : "OK");
+
+    // Authenticated roundtrip (easy interface)
+    crypto_lock(box, key, nonce, plaintext, 8);           // make true message
+    status |= crypto_unlock(out, key, nonce, box, 8+16);  // accept true message
+    status |= crypto_memcmp(plaintext, out, 8);           // roundtrip
+    box[0]++;                                             // make forgery
+    status |= !crypto_unlock(out, key, nonce, box, 8+16); // reject forgery
     printf("%s: aead (simplified)\n", status != 0 ? "FAILED" : "OK");
+    box[0]--; // undo forgery
+
+    // Same result for both interfaces
+    crypto_aead_lock(box2, box2 + 16, key, nonce, 0, 0, plaintext, 8);
+    status |= crypto_memcmp(box, box2, 24);
+    printf("%s: aead (compared)\n", status != 0 ? "FAILED" : "OK");
 
     return status;
 }
index 36ab64dee2641dc95c4cec89af74bc7a7d2a27c9..68480fa6f920bd8f9f917aca7438dd48d6e6ed1c 100644 (file)
@@ -17,3 +17,31 @@ de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f:
 0900000000000000000000000000000000000000000000000000000000000000:
 0900000000000000000000000000000000000000000000000000000000000000:
 422c8e7a6227d7bca1350b3e2bb7279f7897b87bb6854b783c60e80311ae3079:
+
+5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb:
+0000000000000000000000000000000000000000000000000000000000000000:
+0000000000000000000000000000000000000000000000000000000000000000:
+
+5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb:
+0100000000000000000000000000000000000000000000000000000000000000:
+0000000000000000000000000000000000000000000000000000000000000000:
+
+5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb:
+e0eb7a7c3b41b8ae1656e3faf19fc46ada098deb9c32b1fd866205165f49b800:
+0000000000000000000000000000000000000000000000000000000000000000:
+
+5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb:
+5f9c95bca3508c24b1d0b1559c83ef5b04445cc4581c8e86d8224eddd09f1157:
+0000000000000000000000000000000000000000000000000000000000000000:
+
+5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb:
+ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+0000000000000000000000000000000000000000000000000000000000000000:
+
+5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb:
+edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+0000000000000000000000000000000000000000000000000000000000000000:
+
+5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb:
+eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f:
+0000000000000000000000000000000000000000000000000000000000000000: