gpg: Implement AEAD for SKESK packets.
[gnupg.git] / g10 / build-packet.c
index fa2674b..b4e03d0 100644 (file)
@@ -42,6 +42,7 @@ static u32 calc_plaintext( PKT_plaintext *pt );
 static int do_plaintext( IOBUF out, int ctb, PKT_plaintext *pt );
 static int do_encrypted( IOBUF out, int ctb, PKT_encrypted *ed );
 static int do_encrypted_mdc( IOBUF out, int ctb, PKT_encrypted *ed );
+static int do_encrypted_aead (iobuf_t out, int ctb, PKT_encrypted *ed);
 static int do_compressed( IOBUF out, int ctb, PKT_compressed *cd );
 static int do_signature( IOBUF out, int ctb, PKT_signature *sig );
 static int do_onepass_sig( IOBUF out, int ctb, PKT_onepass_sig *ops );
@@ -106,6 +107,7 @@ build_packet (IOBUF out, PACKET *pkt)
       break;
     case PKT_ENCRYPTED:
     case PKT_ENCRYPTED_MDC:
+    case PKT_ENCRYPTED_AEAD:
       new_ctb = pkt->pkt.encrypted->new_ctb;
       break;
     case PKT_COMPRESSED:
@@ -158,6 +160,9 @@ build_packet (IOBUF out, PACKET *pkt)
     case PKT_ENCRYPTED_MDC:
       rc = do_encrypted_mdc (out, ctb, pkt->pkt.encrypted);
       break;
+    case PKT_ENCRYPTED_AEAD:
+      rc = do_encrypted_aead (out, ctb, pkt->pkt.encrypted);
+      break;
     case PKT_COMPRESSED:
       rc = do_compressed (out, ctb, pkt->pkt.compressed);
       break;
@@ -182,8 +187,8 @@ build_packet (IOBUF out, PACKET *pkt)
 
 
 /* Build a packet and write it to the stream OUT.  This variant also
- * writes the meta data using ring tyrust packets.  Returns: 0 on
- * success or on aerror code.  */
+ * writes the meta data using ring trust packets.  Returns: 0 on
+ * success or on error code.  */
 gpg_error_t
 build_packet_and_meta (iobuf_t out, PACKET *pkt)
 {
@@ -213,7 +218,7 @@ build_packet_and_meta (iobuf_t out, PACKET *pkt)
       PKT_user_id *uid = pkt->pkt.user_id;
 
       rt.subtype = RING_TRUST_UID;
-      rt.keysrc = uid->keysrc;
+      rt.keyorg = uid->keyorg;
       rt.keyupdate = uid->keyupdate;
       rt.url = uid->updateurl;
       err = do_ring_trust (out, &rt);
@@ -225,7 +230,7 @@ build_packet_and_meta (iobuf_t out, PACKET *pkt)
       PKT_public_key *pk = pkt->pkt.public_key;
 
       rt.subtype = RING_TRUST_KEY;
-      rt.keysrc = pk->keysrc;
+      rt.keyorg = pk->keyorg;
       rt.keyupdate = pk->keyupdate;
       rt.url = pk->updateurl;
       err = do_ring_trust (out, &rt);
@@ -395,7 +400,7 @@ do_ring_trust (iobuf_t out, PKT_ring_trust *rt)
   iobuf_put (out, rt->subtype);
   if (rt->subtype == RING_TRUST_KEY || rt->subtype == RING_TRUST_UID)
     {
-      iobuf_put (out, rt->keysrc);
+      iobuf_put (out, rt->keyorg);
       write_32 (out, rt->keyupdate);
       iobuf_put (out, namelen);
       if (namelen)
@@ -612,11 +617,8 @@ do_symkey_enc( IOBUF out, int ctb, PKT_symkey_enc *enc )
   IOBUF a = iobuf_temp();
 
   log_assert (ctb_pkttype (ctb) == PKT_SYMKEY_ENC);
+  log_assert (enc->version == 4 || enc->version == 5);
 
-  /* The only acceptable version.  */
-  log_assert( enc->version == 4 );
-
-  /* RFC 4880, Section 3.7.  */
   switch (enc->s2k.mode)
     {
     case 0: /* Simple S2K.  */
@@ -627,23 +629,26 @@ do_symkey_enc( IOBUF out, int ctb, PKT_symkey_enc *enc )
     default:
       log_bug ("do_symkey_enc: s2k=%d\n", enc->s2k.mode);
     }
-    iobuf_put( a, enc->version );
-    iobuf_put( a, enc->cipher_algo );
-    iobuf_put( a, enc->s2k.mode );
-    iobuf_put( a, enc->s2k.hash_algo );
-    if( enc->s2k.mode == 1 || enc->s2k.mode == 3 ) {
-       iobuf_write(a, enc->s2k.salt, 8 );
-       if( enc->s2k.mode == 3 )
-           iobuf_put(a, enc->s2k.count);
+  iobuf_put (a, enc->version);
+  iobuf_put (a, enc->cipher_algo);
+  if (enc->version == 5)
+    iobuf_put (a, enc->aead_algo);
+  iobuf_put (a, enc->s2k.mode);
+  iobuf_put (a, enc->s2k.hash_algo);
+  if (enc->s2k.mode == 1 || enc->s2k.mode == 3)
+    {
+      iobuf_write (a, enc->s2k.salt, 8);
+      if (enc->s2k.mode == 3)
+        iobuf_put (a, enc->s2k.count);
     }
-    if( enc->seskeylen )
-       iobuf_write(a, enc->seskey, enc->seskeylen );
+  if (enc->seskeylen)
+    iobuf_write (a, enc->seskey, enc->seskeylen);
 
-    write_header(out, ctb, iobuf_get_temp_length(a) );
-    rc = iobuf_write_temp( out, a );
+  write_header (out, ctb, iobuf_get_temp_length(a));
+  rc = iobuf_write_temp (out, a);
 
-    iobuf_close(a);
-    return rc;
+  iobuf_close (a);
+  return rc;
 }
 
 
@@ -812,6 +817,32 @@ do_encrypted_mdc( IOBUF out, int ctb, PKT_encrypted *ed )
 }
 
 
+/* Serialize the symmetrically AEAD encrypted data packet
+ * (rfc4880bis-03, Section 5.16) described by ED and write it to OUT.
+ *
+ * Note: this only writes only packet's header.  The caller must then
+ * follow up and write the actual encrypted data.  This should be done
+ * by pushing the the cipher_filter_aead.  */
+static int
+do_encrypted_aead (iobuf_t out, int ctb, PKT_encrypted *ed)
+{
+  u32 n;
+
+  log_assert (ctb_pkttype (ctb) == PKT_ENCRYPTED_AEAD);
+
+  n = ed->len ? (ed->len + ed->extralen + 4) : 0;
+  write_header (out, ctb, n );
+  iobuf_writebyte (out, 1); /* Version.  */
+  iobuf_writebyte (out, ed->cipher_algo);
+  iobuf_writebyte (out, ed->aead_algo);
+  iobuf_writebyte (out, ed->chunkbyte);
+
+  /* This is all. The caller has to write the encrypted data */
+
+  return 0;
+}
+
+
 /* Serialize the compressed packet (RFC 4880, Section 5.6) described
    by CD and write it to OUT.