]> Repositorios git - scryer-prolog.git/commitdiff
ADDED: library(crypto): Support for additional authenticated data (AAD).
authorMarkus Triska <[email protected]>
Wed, 5 Aug 2020 18:09:07 +0000 (20:09 +0200)
committerMarkus Triska <[email protected]>
Wed, 5 Aug 2020 18:09:07 +0000 (20:09 +0200)
Additional authenticated data can now be specified with the new
aad(Chars) option for encryption and decryption. It is authenticated,
but not encrypted.

src/clause_types.rs
src/lib/crypto.pl
src/machine/system_calls.rs

index 045093087db807a7a05b2414896c2b5a9b5255ac..3f1fee682ca553b409d419ee5a8a4d38f136de9a 100644 (file)
@@ -710,7 +710,7 @@ impl SystemClauseType {
             ("$crypto_data_hash", 4) => Some(SystemClauseType::CryptoDataHash),
             ("$crypto_data_hkdf", 7) => Some(SystemClauseType::CryptoDataHKDF),
             ("$crypto_password_hash", 4) => Some(SystemClauseType::CryptoPasswordHash),
-            ("$crypto_data_encrypt", 6) => Some(SystemClauseType::CryptoDataEncrypt),
+            ("$crypto_data_encrypt", 7) => Some(SystemClauseType::CryptoDataEncrypt),
             ("$crypto_data_decrypt", 6) => Some(SystemClauseType::CryptoDataDecrypt),
             ("$crypto_curve_scalar_mult", 5) => Some(SystemClauseType::CryptoCurveScalarMult),
             ("$ed25519_sign", 5) => Some(SystemClauseType::Ed25519Sign),
index 49aae46e07911db3eee3f7e1458e605a56e2a2b2..7daab5999a122f64f365f2c89d6bce8263a77ded 100644 (file)
@@ -492,6 +492,12 @@ bytes_base64(Bytes, Base64) :-
       list of _bytes_ holding the tag. This tag must be provided for
       decryption.
 
+      - aad(+Data)
+      Data is additional authenticated data (AAD), a list of
+      characters. It is authenticated in that it influences the tag,
+      but it is not encrypted. The encoding/1 option also specifies
+      the encoding of Data.
+
    Here is an example encryption and decryption, using the ChaCha20
    stream cipher with the Poly1305 authenticator. This cipher uses a
    256-bit key and a 96-bit nonce, i.e., 32 and 12 _bytes_,
@@ -533,13 +539,15 @@ crypto_data_encrypt(PlainText0, Algorithm, Key, IV, CipherText, Options) :-
             must_be_bytes(Tag, crypto_data_encrypt/6)
         ;   true
         ),
+        option(aad(AAD0), Options, []),
+        encoding_chars(Encoding, AAD0, AAD),
         must_be_bytes(Key, crypto_data_encrypt/6),
         must_be_bytes(IV, crypto_data_encrypt/6),
         must_be(atom, Algorithm),
         (   Algorithm = 'chacha20-poly1305' -> true
         ;   domain_error('chacha20-poly1305', Algorithm, crypto_data_encrypt/6)
         ),
-        '$crypto_data_encrypt'(PlainText, Encoding, Key, IV, Tag, CipherText).
+        '$crypto_data_encrypt'(PlainText, AAD, Encoding, Key, IV, Tag, CipherText).
 
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
   crypto_data_decrypt(+CipherText,
@@ -567,6 +575,10 @@ crypto_data_encrypt(PlainText0, Algorithm, Key, IV, CipherText, Options) :-
     - tag(+Tag)
     For authenticated encryption schemes, the tag must be specified as
     a list of bytes exactly as they were generated upon encryption.
+
+    - aad(+Data)
+    Any additional authenticated data (AAD) must be specified. The
+    encoding/1 option also specifies the encoding of Data.
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
 crypto_data_decrypt(CipherText0, Algorithm, Key, IV, PlainText, Options) :-
@@ -576,6 +588,8 @@ crypto_data_decrypt(CipherText0, Algorithm, Key, IV, PlainText, Options) :-
         must_be_bytes(IV, crypto_data_decrypt/6),
         must_be(atom, Algorithm),
         option(encoding(Encoding), Options, utf8),
+        option(aad(AAD0), Options, []),
+        encoding_chars(Encoding, AAD0, AAD),
         must_be(atom, Encoding),
         member(Encoding, [utf8,octet]),
         must_be(list, CipherText0),
@@ -585,7 +599,7 @@ crypto_data_decrypt(CipherText0, Algorithm, Key, IV, PlainText, Options) :-
         (   Algorithm = 'chacha20-poly1305' -> true
         ;   domain_error('chacha20-poly1305', Algorithm, crypto_data_decrypt/6)
         ),
-        '$crypto_data_decrypt'(CipherText, octet, Key, IV, Encoding, PlainText).
+        '$crypto_data_decrypt'(CipherText, AAD, Key, IV, Encoding, PlainText).
 
 
 encoding_chars(octet, Bs, Cs) :-
index ada49a0ff9674945f524173e7133b11203cc5d5e..f938140a99dd1b061541c68250ccb23671cbe372 100644 (file)
@@ -5388,7 +5388,8 @@ impl MachineState {
                 self.unify(arg, byte);
             }
             &SystemClauseType::CryptoDataHash => {
-                let bytes = self.string_encoding_bytes(1, 2);
+                let encoding = self.atom_argument_to_string(2);
+                let bytes = self.string_encoding_bytes(1, &encoding);
 
                 let algorithm_str = match self.store(self.deref(self[temp_v!(4)])) {
                     Addr::Con(h) if self.heap.atom_at(h) => {
@@ -5442,7 +5443,8 @@ impl MachineState {
                 self.unify(self[temp_v!(3)], ints_list);
             }
             &SystemClauseType::CryptoDataHKDF => {
-                let data = self.string_encoding_bytes(1, 2);
+                let encoding = self.atom_argument_to_string(2);
+                let data = self.string_encoding_bytes(1, &encoding);
                 let stub1 = MachineError::functor_stub(clause_name!("crypto_data_hkdf"), 4);
                 let salt = self.integers_to_bytevec(temp_v!(3), stub1);
                 let stub2 = MachineError::functor_stub(clause_name!("crypto_data_hkdf"), 4);
@@ -5530,11 +5532,13 @@ impl MachineState {
                 self.unify(self[temp_v!(4)], ints_list);
             }
             &SystemClauseType::CryptoDataEncrypt => {
-                let data = self.string_encoding_bytes(1, 2);
-                let stub2 = MachineError::functor_stub(clause_name!("crypto_data_encrypt"), 6);
-                let key = self.integers_to_bytevec(temp_v!(3), stub2);
-                let stub3 = MachineError::functor_stub(clause_name!("crypto_data_encrypt"), 6);
-                let iv = self.integers_to_bytevec(temp_v!(4), stub3);
+                let encoding = self.atom_argument_to_string(3);
+                let data = self.string_encoding_bytes(1, &encoding);
+                let aad = self.string_encoding_bytes(2, &encoding);
+                let stub2 = MachineError::functor_stub(clause_name!("crypto_data_encrypt"), 7);
+                let key = self.integers_to_bytevec(temp_v!(4), stub2);
+                let stub3 = MachineError::functor_stub(clause_name!("crypto_data_encrypt"), 7);
+                let iv = self.integers_to_bytevec(temp_v!(5), stub3);
 
                 let unbound_key = aead::UnboundKey::new(&aead::CHACHA20_POLY1305, &key).unwrap();
                 let nonce = aead::Nonce::try_assume_unique_for_key(&iv).unwrap();
@@ -5542,7 +5546,7 @@ impl MachineState {
 
                 let mut in_out = data.clone();
                 let tag =
-                     match key.seal_in_place_separate_tag(nonce, aead::Aad::empty(), &mut in_out) {
+                     match key.seal_in_place_separate_tag(nonce, aead::Aad::from(aad), &mut in_out) {
                         Ok(d) => { d }
                         _     => { self.fail = true; return Ok(()); }
                       };
@@ -5555,29 +5559,18 @@ impl MachineState {
                           self.heap.put_complete_string(&buffer)
                       };
 
-                self.unify(self[temp_v!(5)], tag_list);
-                self.unify(self[temp_v!(6)], complete_string);
+                self.unify(self[temp_v!(6)], tag_list);
+                self.unify(self[temp_v!(7)], complete_string);
             }
             &SystemClauseType::CryptoDataDecrypt => {
-                let data = self.string_encoding_bytes(1, 2);
-                let stub1 = MachineError::functor_stub(clause_name!("crypto_data_decrypt"), 6);
+                let data = self.string_encoding_bytes(1, "octet");
+                let encoding = self.atom_argument_to_string(5);
+                let aad = self.string_encoding_bytes(2, &encoding);
+                let stub1 = MachineError::functor_stub(clause_name!("crypto_data_decrypt"), 7);
                 let key = self.integers_to_bytevec(temp_v!(3), stub1);
-                let stub2 = MachineError::functor_stub(clause_name!("crypto_data_decrypt"), 6);
+                let stub2 = MachineError::functor_stub(clause_name!("crypto_data_decrypt"), 7);
                 let iv = self.integers_to_bytevec(temp_v!(4), stub2);
 
-                let encoding = match self.store(self.deref(self[temp_v!(5)])) {
-                    Addr::Con(h) if self.heap.atom_at(h) => {
-                        if let HeapCellValue::Atom(ref atom, _) = &self.heap[h] {
-                            atom.as_str()
-                        } else {
-                            unreachable!()
-                        }
-                    }
-                    _ => {
-                        unreachable!()
-                    }
-                };
-
                 let unbound_key = aead::UnboundKey::new(&aead::CHACHA20_POLY1305, &key).unwrap();
                 let nonce = aead::Nonce::try_assume_unique_for_key(&iv).unwrap();
                 let key = aead::LessSafeKey::new(unbound_key);
@@ -5586,12 +5579,12 @@ impl MachineState {
 
                 let complete_string = {
                           let decrypted_data =
-                                match key.open_in_place(nonce, aead::Aad::empty(), &mut in_out) {
+                                match key.open_in_place(nonce, aead::Aad::from(aad), &mut in_out) {
                                    Ok(d) => { d }
                                    _     => { self.fail = true; return Ok(()); }
                                  };
 
-                          let buffer = match encoding {
+                          let buffer = match encoding.as_str() {
                                   "octet" => { String::from_iter(decrypted_data.iter().map(|b| *b as char)) }
                                   "utf8"  => { match String::from_utf8(decrypted_data.to_vec()) {
                                                   Ok(str) => { str }
@@ -5665,7 +5658,8 @@ impl MachineState {
                 self.unify(self[temp_v!(1)], complete_string);
             }
             &SystemClauseType::Ed25519KeyPairPublicKey => {
-                let bytes = self.string_encoding_bytes(1, 2);
+                let encoding = self.atom_argument_to_string(2);
+                let bytes = self.string_encoding_bytes(1, &encoding);
 
                 let key_pair = match signature::Ed25519KeyPair::from_pkcs8(&bytes) {
                                   Ok(kp) => { kp }
@@ -5680,8 +5674,9 @@ impl MachineState {
                 self.unify(self[temp_v!(3)], complete_string);
             }
             &SystemClauseType::Ed25519Sign => {
-                let key = self.string_encoding_bytes(1, 2);
-                let data = self.string_encoding_bytes(3, 4);
+                let key = self.string_encoding_bytes(1, "octet");
+                let encoding = self.atom_argument_to_string(4);
+                let data = self.string_encoding_bytes(3, &encoding);
 
                 let key_pair = match signature::Ed25519KeyPair::from_pkcs8(&key) {
                                   Ok(kp) => { kp }
@@ -5696,8 +5691,9 @@ impl MachineState {
                 self.unify(self[temp_v!(5)], sig_list);
             }
             &SystemClauseType::Ed25519Verify => {
-                let key = self.string_encoding_bytes(1, 2);
-                let data = self.string_encoding_bytes(3, 4);
+                let key = self.string_encoding_bytes(1, "octet");
+                let encoding = self.atom_argument_to_string(4);
+                let data = self.string_encoding_bytes(3, &encoding);
                 let stub = MachineError::functor_stub(clause_name!("ed25519_verify"), 5);
                 let signature = self.integers_to_bytevec(temp_v!(5), stub);
 
@@ -5863,17 +5859,14 @@ impl MachineState {
     }
 
     pub(super)
-    fn string_encoding_bytes(
+    fn atom_argument_to_string(
         &mut self,
-        data_arg: usize,
-        encoding_arg: usize,
-    ) -> Vec<u8> {
-        let data = self.heap_pstr_iter(self[temp_v!(data_arg)]).to_string();
-
-        let encoding_str = match self.store(self.deref(self[temp_v!(encoding_arg)])) {
+        atom_arg: usize,
+    ) -> String {
+        match self.store(self.deref(self[temp_v!(atom_arg)])) {
             Addr::Con(h) if self.heap.atom_at(h) => {
                 if let HeapCellValue::Atom(ref atom, _) = &self.heap[h] {
-                    atom.as_str()
+                    atom.as_str().to_string()
                 } else {
                     unreachable!()
                 }
@@ -5881,9 +5874,18 @@ impl MachineState {
             _ => {
                 unreachable!()
             }
-        };
+        }
+    }
+
+    pub(super)
+    fn string_encoding_bytes(
+        &mut self,
+        data_arg: usize,
+        encoding: &str,
+    ) -> Vec<u8> {
+        let data = self.heap_pstr_iter(self[temp_v!(data_arg)]).to_string();
 
-        match encoding_str {
+        match encoding {
             "utf8" => { data.into_bytes() }
             "octet" => {
                 let mut buf = vec![];