libaacs | branch: master | npzacs <npz...@gmail.com> | Thu Aug 16 15:53:39 2018 
+0300| [a5de7f32a5a02b651b714fb90f36b2bc0e1a9079] | committer: npzacs

crypto: parametrize ECDSA curve, hash algorithm and key size

> http://git.videolan.org/gitweb.cgi/libaacs.git/?a=commit;h=a5de7f32a5a02b651b714fb90f36b2bc0e1a9079
---

 src/libaacs/crypto.c | 101 ++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 68 insertions(+), 33 deletions(-)

diff --git a/src/libaacs/crypto.c b/src/libaacs/crypto.c
index d150a44..200e401 100644
--- a/src/libaacs/crypto.c
+++ b/src/libaacs/crypto.c
@@ -249,15 +249,32 @@ void crypto_aes_cmac_16(const unsigned char *data, const 
unsigned char *aes_key,
  * build S-expressions
  */
 
+static const char *_aacs1_curve(void)
+{
+  return
+    "(p #00"AACS_EC_p"#)"
+    "(a #00"AACS_EC_a"#)"
+    "(b #00"AACS_EC_b"#)"
+    "(g #04"
+        AACS_EC_G_x
+        AACS_EC_G_y
+    "#)"
+    "(n #00"AACS_EC_n"#)";
+}
+
 static gcry_error_t _aacs_sexp_key(gcry_sexp_t *p_sexp_key,
                                    const uint8_t *q_x, const uint8_t *q_y,
-                                   const uint8_t *priv_key)
+                                   const uint8_t *priv_key,
+                                   const char *curve,
+                                   size_t key_len)
 {
     gcry_mpi_t    mpi_d = NULL;
     unsigned char Q[41];
     char          str_Q[sizeof(Q) * 2 + 1];
     gcry_error_t  err;
 
+    BD_ASSERT (key_len == 20);
+
     /* Assign MPI values for ECDSA parameters Q and d.
      * Values are:
      *   Q.x = c[12]..c[31]
@@ -267,17 +284,17 @@ static gcry_error_t _aacs_sexp_key(gcry_sexp_t 
*p_sexp_key,
      * Note: The MPI values for Q are in the form "<format>||Q.x||Q.y".
      */
     memcpy(&Q[0],  "\x04", 1); // format
-    memcpy(&Q[1],  q_x, 20);   // Q.x
-    memcpy(&Q[21], q_y, 20);   // Q.y
+    memcpy(&Q[1],  q_x, key_len);   // Q.x
+    memcpy(&Q[1 + key_len], q_y, key_len);   // Q.y
     if (priv_key) {
-        gcry_mpi_scan(&mpi_d, GCRYMPI_FMT_USG, priv_key, 20, NULL);
+        gcry_mpi_scan(&mpi_d, GCRYMPI_FMT_USG, priv_key, key_len, NULL);
     }
 
     /* Show the values of the MPIs Q.x, Q.y, and d when debugging */
     if (GCRYPT_DEBUG) {
         gcry_mpi_t mpi_Q_x, mpi_Q_y;
-        gcry_mpi_scan(&mpi_Q_x, GCRYMPI_FMT_USG, q_x, 20, NULL);
-        gcry_mpi_scan(&mpi_Q_y, GCRYMPI_FMT_USG, q_y, 20, NULL);
+        gcry_mpi_scan(&mpi_Q_x, GCRYMPI_FMT_USG, q_x, key_len, NULL);
+        gcry_mpi_scan(&mpi_Q_y, GCRYMPI_FMT_USG, q_y, key_len, NULL);
         gcry_mpi_dump(mpi_Q_x);
         printf("\n");
         gcry_mpi_dump(mpi_Q_y);
@@ -303,22 +320,16 @@ static gcry_error_t _aacs_sexp_key(gcry_sexp_t 
*p_sexp_key,
     /* Points are currently only supported in standard format, so get a
      * hexstring out of Q.
      */
-    hex_array_to_hexstring(str_Q, Q, sizeof(Q));
+    hex_array_to_hexstring(str_Q, Q, 1 + 2*key_len);
 
     char *strfmt = str_printf(
       "(%s"
       "(ecdsa"
-      "(p #00"AACS_EC_p"#)"
-      "(a #00"AACS_EC_a"#)"
-      "(b #00"AACS_EC_b"#)"
-      "(g #04"
-          AACS_EC_G_x
-          AACS_EC_G_y
-          "#)"
-      "(n #00"AACS_EC_n"#)"
+      "%s"
       "(q #%s#)"
       "%s))",
       mpi_d ? "private-key" : "public-key",
+      curve,
       str_Q,
       mpi_d ? "(d %m)" : ""
       );
@@ -348,15 +359,26 @@ error:
     return err;
 }
 
-static gcry_error_t _aacs_sexp_sha1(gcry_sexp_t *p_sexp_data,
-                                    const uint8_t *block, uint32_t len)
+static gcry_error_t _aacs_sexp_hash(gcry_sexp_t *p_sexp_data,
+                                    const uint8_t *block, uint32_t len,
+                                    enum gcry_md_algos hash_type)
 {
     gcry_mpi_t   mpi_md = NULL;
     uint8_t      md[20];
     gcry_error_t err;
+    size_t hash_size;
 
-    gcry_md_hash_buffer(GCRY_MD_SHA1, md, block, len);
-    gcry_mpi_scan(&mpi_md, GCRYMPI_FMT_USG, md, sizeof(md), NULL);
+    switch (hash_type) {
+    case GCRY_MD_SHA1:
+        hash_size = 20;
+        break;
+    default:
+        BD_ASSERT_UNREACHABLE ("unsupported hash algorithm");
+        return GPG_ERR_UNKNOWN_ALGORITHM;
+    }
+
+    gcry_md_hash_buffer(hash_type, md, block, len);
+    gcry_mpi_scan(&mpi_md, GCRYMPI_FMT_USG, md, hash_size, NULL);
 
     /* Dump information about the md MPI when debugging */
     if (GCRYPT_DEBUG) {
@@ -396,14 +418,15 @@ static gcry_error_t _aacs_sexp_sha1(gcry_sexp_t 
*p_sexp_data,
 }
 
 static gcry_error_t _aacs_sexp_signature(gcry_sexp_t *p_sexp_sign,
-                                         const uint8_t *signature)
+                                         const uint8_t *signature,
+                                         size_t key_len)
 {
     gcry_mpi_t   mpi_r = NULL;
     gcry_mpi_t   mpi_s = NULL;
     gcry_error_t err;
 
-    gcry_mpi_scan(&mpi_r, GCRYMPI_FMT_USG, signature,      20, NULL);
-    gcry_mpi_scan(&mpi_s, GCRYMPI_FMT_USG, signature + 20, 20, NULL);
+    gcry_mpi_scan(&mpi_r, GCRYMPI_FMT_USG, signature,           key_len, NULL);
+    gcry_mpi_scan(&mpi_s, GCRYMPI_FMT_USG, signature + key_len, key_len, NULL);
 
     /* Dump information about the md MPI when debugging */
     if (GCRYPT_DEBUG) {
@@ -447,7 +470,7 @@ void crypto_aacs_sign(const uint8_t *cert, const uint8_t 
*priv_key, uint8_t *sig
     gcry_error_t err;
 
     GCRY_VERIFY("_aacs_sexp_key",
-                _aacs_sexp_key(&sexp_key, cert + 12, cert + 32, priv_key));
+                _aacs_sexp_key(&sexp_key, cert + 12, cert + 32, priv_key, 
_aacs1_curve(), 20));
 
     /* Calculate the sha1 hash from the nonce and host key point and covert
      * the hash into an MPI.
@@ -455,8 +478,8 @@ void crypto_aacs_sign(const uint8_t *cert, const uint8_t 
*priv_key, uint8_t *sig
     memcpy(&block[0], nonce, 20);
     memcpy(&block[20], point, 40);
 
-    GCRY_VERIFY("_aacs_sexp_sha1",
-                _aacs_sexp_sha1(&sexp_data, block, sizeof(block)));
+    GCRY_VERIFY("_aacs_sexp_hash",
+                _aacs_sexp_hash(&sexp_data, block, sizeof(block), 
GCRY_MD_SHA1));
 
     /* Sign the hash with the ECDSA key. The resulting s-expression should be
      * in the form:
@@ -501,7 +524,7 @@ void crypto_aacs_sign(const uint8_t *cert, const uint8_t 
*priv_key, uint8_t *sig
     gcry_mpi_release(mpi_s);
 }
 
-static int _aacs_verify(const uint8_t *signature,
+static int _aacs_verify(const uint8_t *signature, enum gcry_md_algos hash_type,
                         const uint8_t *q_x, const uint8_t *q_y,
                         const uint8_t *data, uint32_t len)
 {
@@ -509,15 +532,27 @@ static int _aacs_verify(const uint8_t *signature,
     gcry_sexp_t  sexp_sig  = NULL;
     gcry_sexp_t  sexp_data = NULL;
     gcry_error_t err;
+    const char *curve;
+    size_t key_len;
+
+    switch (hash_type) {
+    case GCRY_MD_SHA1:
+        curve = _aacs1_curve();
+        key_len = 20;
+        break;
+    default:
+        BD_ASSERT_UNREACHABLE ("invalid signature size");
+        return 0;
+    }
 
     GCRY_VERIFY("_aacs_sexp_key",
-                _aacs_sexp_key(&sexp_key, q_x, q_y, NULL));
+                _aacs_sexp_key(&sexp_key, q_x, q_y, NULL, curve, key_len));
 
-    GCRY_VERIFY("_aacs_sexp_sha1",
-                _aacs_sexp_sha1(&sexp_data, data, len));
+    GCRY_VERIFY("_aacs_sexp_hash",
+                _aacs_sexp_hash(&sexp_data, data, len, hash_type));
 
     GCRY_VERIFY("_aacs_sexp_signature",
-                _aacs_sexp_signature(&sexp_sig, signature));
+                _aacs_sexp_signature(&sexp_sig, signature, key_len));
 
     GCRY_VERIFY("gcry_pk_verify",
                 gcry_pk_verify(sexp_sig, sexp_data, sexp_key));
@@ -532,7 +567,7 @@ static int _aacs_verify(const uint8_t *signature,
 
 int crypto_aacs_verify(const uint8_t *cert, const uint8_t *signature, const 
uint8_t *data, uint32_t len)
 {
-    return !_aacs_verify(signature, cert + 12, cert + 32, data, len);
+    return !_aacs_verify(signature, GCRY_MD_SHA1, cert + 12, cert + 32, data, 
len);
 }
 
 int  crypto_aacs_verify_aacsla(const uint8_t *signature, const uint8_t *data, 
uint32_t len)
@@ -542,7 +577,7 @@ int  crypto_aacs_verify_aacsla(const uint8_t *signature, 
const uint8_t *data, ui
     static const uint8_t aacs_la_pubkey_y[] = {0x13, 0x7E, 0xC6, 0x38, 0x81, 
0x8F, 0xD9, 0x8F, 0xA4, 0xC3,
                                                0x0B, 0x99, 0x67, 0x28, 0xBF, 
0x4B, 0x91, 0x7F, 0x6A, 0x27 };
 
-    return !_aacs_verify(signature, aacs_la_pubkey_x, aacs_la_pubkey_y, data, 
len);
+    return !_aacs_verify(signature, GCRY_MD_SHA1, aacs_la_pubkey_x, 
aacs_la_pubkey_y, data, len);
 }
 
 int  crypto_aacs_verify_aacscc(const uint8_t *signature, const uint8_t *data, 
uint32_t len)
@@ -552,7 +587,7 @@ int  crypto_aacs_verify_aacscc(const uint8_t *signature, 
const uint8_t *data, ui
     static const uint8_t aacs_cc_pubkey_y[] = { 0x00, 0x1D, 0xF3, 0x6B, 0x8F, 
0x2E, 0xCF, 0x83, 0xCD, 0xEE,
                                                 0x43, 0x8F, 0x7F, 0xD1, 0xF4, 
0x80, 0x6F, 0xD2, 0x0D, 0xE7 };
 
-    return !_aacs_verify(signature, aacs_cc_pubkey_x, aacs_cc_pubkey_y, data, 
len);
+    return !_aacs_verify(signature, GCRY_MD_SHA1, aacs_cc_pubkey_x, 
aacs_cc_pubkey_y, data, len);
 }
 
 static int crypto_aacs_verify_cert(const uint8_t *cert)

_______________________________________________
libaacs-devel mailing list
libaacs-devel@videolan.org
https://mailman.videolan.org/listinfo/libaacs-devel

Reply via email to