[or-cvs] r17610: {tor} Add cross-certification to authority key certificates. Parti (in tor/trunk: . doc/spec doc/spec/proposals src/or src/tools)

nickm at seul.org nickm at seul.org
Fri Dec 12 18:31:39 UTC 2008


Author: nickm
Date: 2008-12-12 13:31:39 -0500 (Fri, 12 Dec 2008)
New Revision: 17610

Modified:
   tor/trunk/ChangeLog
   tor/trunk/doc/spec/dir-spec.txt
   tor/trunk/doc/spec/proposals/157-specific-cert-download.txt
   tor/trunk/src/or/or.h
   tor/trunk/src/or/routerparse.c
   tor/trunk/src/or/test.c
   tor/trunk/src/or/test_data.c
   tor/trunk/src/tools/tor-gencert.c
Log:
Add cross-certification to authority key certificates.  Partial implementation of proposal 157.

Modified: tor/trunk/ChangeLog
===================================================================
--- tor/trunk/ChangeLog	2008-12-12 17:36:08 UTC (rev 17609)
+++ tor/trunk/ChangeLog	2008-12-12 18:31:39 UTC (rev 17610)
@@ -19,6 +19,9 @@
     - Try not to open more than one descriptor-downloading connection to an
       authority at once.  This should reduce load on directory authorities.
       Fixes bug 366.
+    - Add cross-certification to newly generated certificates, so that
+      a signing key is enough information to use to look up a certificate.
+      Partial implementation of proposal 157.
 
   o Minor features (controller):
     - New CONSENSUS_ARRIVED event to note when a new consensus has

Modified: tor/trunk/doc/spec/dir-spec.txt
===================================================================
--- tor/trunk/doc/spec/dir-spec.txt	2008-12-12 17:36:08 UTC (rev 17609)
+++ tor/trunk/doc/spec/dir-spec.txt	2008-12-12 18:31:39 UTC (rev 17610)
@@ -758,6 +758,25 @@
         The directory server's public signing key.  This key MUST be at
         least 1024 bits, and MAY be longer.
 
+    "dir-key-crosscert" NL CrossSignature NL
+
+        [At most once.]
+
+        NOTE: Authorities MUST include this field in all newly generated
+        certificates.  A future version of this specification will make
+        the field required.
+
+        CrossSignature is a signature, made using the certificate's signing
+        key, of the digest of the PKCS1-padded hash of the certificate's
+        identity key.  For backward compatibility with broken versions of the
+        parser, we wrap the base64-encoded signature in -----BEGIN ID
+        SIGNATURE---- and -----END ID SIGNATURE----- tags.  Implementations
+        MUST allow the "ID " portion to be omitted, however.
+
+        When encountering a certificate with a dir-key-crosscert entry,
+        implementations MUST verify that the signature is a correct signature
+        of the hash of the identity key using the signing key.
+
     "dir-key-certification" NL Signature NL
 
         [At end, exactly once.]

Modified: tor/trunk/doc/spec/proposals/157-specific-cert-download.txt
===================================================================
--- tor/trunk/doc/spec/proposals/157-specific-cert-download.txt	2008-12-12 17:36:08 UTC (rev 17609)
+++ tor/trunk/doc/spec/proposals/157-specific-cert-download.txt	2008-12-12 18:31:39 UTC (rev 17610)
@@ -13,6 +13,11 @@
      Changed name of cross certification field to match the other authority
      certificate fields.
 
+Status:
+
+  Cross-certification is implemented for new certificates, but not yet
+  required.
+
 Overview:
 
   Tor's directory specification gives two ways to download a certificate:

Modified: tor/trunk/src/or/or.h
===================================================================
--- tor/trunk/src/or/or.h	2008-12-12 17:36:08 UTC (rev 17609)
+++ tor/trunk/src/or/or.h	2008-12-12 18:31:39 UTC (rev 17610)
@@ -1729,6 +1729,7 @@
   time_t expires;
   uint32_t addr;
   uint16_t dir_port;
+  uint8_t is_cross_certified;
 } authority_cert_t;
 
 /** Bitfield enum type listing types of directory authority/directory

Modified: tor/trunk/src/or/routerparse.c
===================================================================
--- tor/trunk/src/or/routerparse.c	2008-12-12 17:36:08 UTC (rev 17609)
+++ tor/trunk/src/or/routerparse.c	2008-12-12 18:31:39 UTC (rev 17610)
@@ -70,6 +70,7 @@
   K_DIR_KEY_PUBLISHED,
   K_DIR_KEY_EXPIRES,
   K_DIR_KEY_CERTIFICATION,
+  K_DIR_KEY_CROSSCERT,
   K_DIR_ADDRESS,
 
   K_VOTE_STATUS,
@@ -328,6 +329,7 @@
   T1("dir-key-published",K_DIR_KEY_PUBLISHED,        CONCAT_ARGS, NO_OBJ),   \
   T1("dir-key-expires",  K_DIR_KEY_EXPIRES,          CONCAT_ARGS, NO_OBJ),   \
   T1("dir-signing-key",  K_DIR_SIGNING_KEY,          NO_ARGS,     NEED_KEY ),\
+  T01("dir-key-crosscert", K_DIR_KEY_CROSSCERT,       NO_ARGS,    NEED_OBJ ),\
   T1("dir-key-certification", K_DIR_KEY_CERTIFICATION,                       \
                                                      NO_ARGS,     NEED_OBJ), \
   T01("dir-address",     K_DIR_ADDRESS,              GE(1),       NO_OBJ),
@@ -468,10 +470,12 @@
                                          const char **s,
                                          const char *eos,
                                          token_rule_t *table);
+#define CST_CHECK_AUTHORITY   (1<<0)
+#define CST_NO_CHECK_OBJTYPE  (1<<1)
 static int check_signature_token(const char *digest,
                                  directory_token_t *tok,
                                  crypto_pk_env_t *pkey,
-                                 int check_authority,
+                                 int flags,
                                  const char *doctype);
 static crypto_pk_env_t *find_dir_signing_key(const char *str, const char *eos);
 static int tor_version_same_series(tor_version_t *a, tor_version_t *b);
@@ -714,7 +718,8 @@
   }
   declared_key = find_dir_signing_key(str, str+strlen(str));
   note_crypto_pk_op(VERIFY_DIR);
-  if (check_signature_token(digest, tok, declared_key, 1, "directory")<0)
+  if (check_signature_token(digest, tok, declared_key,
+                            CST_CHECK_AUTHORITY, "directory")<0)
     goto err;
 
   SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
@@ -805,7 +810,8 @@
   }
   declared_key = find_dir_signing_key(str, eos);
   note_crypto_pk_op(VERIFY_DIR);
-  if (check_signature_token(digest, tok, declared_key, 1, "running-routers")
+  if (check_signature_token(digest, tok, declared_key,
+                            CST_CHECK_AUTHORITY, "running-routers")
       < 0)
     goto err;
 
@@ -896,18 +902,22 @@
 
 /** Check whether the object body of the token in <b>tok</b> has a good
  * signature for <b>digest</b> using key <b>pkey</b>.  If
- * <b>check_authority</b> is set, make sure that <b>pkey</b> is the key of a
- * directory authority.  Use <b>doctype</b> as the type of the document when
- * generating log messages.  Return 0 on success, negative on failure.
+ * <b>CST_CHECK_AUTHORITY</b> is set, make sure that <b>pkey</b> is the key of
+ * a directory authority.  If <b>CST_NO_CHECK_OBJTYPE</b> is set, do not check
+ * the object type of the signature object. Use <b>doctype</b> as the type of
+ * the document when generating log messages.  Return 0 on success, negative
+ * on failure.
  */
 static int
 check_signature_token(const char *digest,
                       directory_token_t *tok,
                       crypto_pk_env_t *pkey,
-                      int check_authority,
+                      int flags,
                       const char *doctype)
 {
   char *signed_digest;
+  const int check_authority = (flags & CST_CHECK_AUTHORITY);
+  const int check_objtype = ! (flags & CST_NO_CHECK_OBJTYPE);
 
   tor_assert(pkey);
   tor_assert(tok);
@@ -920,9 +930,11 @@
     return -1;
   }
 
-  if (strcmp(tok->object_type, "SIGNATURE")) {
-    log_warn(LD_DIR, "Bad object type on %s signature", doctype);
-    return -1;
+  if (check_objtype) {
+    if (strcmp(tok->object_type, "SIGNATURE")) {
+      log_warn(LD_DIR, "Bad object type on %s signature", doctype);
+      return -1;
+    }
   }
 
   signed_digest = tor_malloc(tok->object_size);
@@ -1664,6 +1676,7 @@
       log_debug(LD_DIR, "We already checked the signature on this "
                 "certificate; no need to do so again.");
       found = 1;
+      cert->is_cross_certified = old_cert->is_cross_certified;
     }
   }
   if (!found) {
@@ -1671,6 +1684,19 @@
                               "key certificate")) {
       goto err;
     }
+
+    if ((tok = find_opt_by_keyword(tokens, K_DIR_KEY_CROSSCERT))) {
+      /* XXXX Once all authorities generate cross-certified certificates,
+       * make this field mandatory. */
+      if (check_signature_token(cert->cache_info.identity_digest,
+                                tok,
+                                cert->signing_key,
+                                CST_NO_CHECK_OBJTYPE,
+                                "key cross-certification")) {
+        goto err;
+      }
+      cert->is_cross_certified = 1;
+    }
   }
 
   cert->cache_info.signed_descriptor_len = len;

Modified: tor/trunk/src/or/test.c
===================================================================
--- tor/trunk/src/or/test.c	2008-12-12 17:36:08 UTC (rev 17609)
+++ tor/trunk/src/or/test.c	2008-12-12 18:31:39 UTC (rev 17610)
@@ -3084,6 +3084,7 @@
   /* Parse certificates and keys. */
   cert1 = authority_cert_parse_from_string(AUTHORITY_CERT_1, NULL);
   test_assert(cert1);
+  test_assert(cert1->is_cross_certified);
   cert2 = authority_cert_parse_from_string(AUTHORITY_CERT_2, NULL);
   test_assert(cert2);
   cert3 = authority_cert_parse_from_string(AUTHORITY_CERT_3, NULL);
@@ -3360,15 +3361,15 @@
   test_eq(4, smartlist_len(con->voters)); /*3 voters, 1 legacy key.*/
   /* The voter id digests should be in this order. */
   test_assert(memcmp(cert2->cache_info.identity_digest,
+                     cert1->cache_info.identity_digest,DIGEST_LEN)<0);
+  test_assert(memcmp(cert1->cache_info.identity_digest,
                      cert3->cache_info.identity_digest,DIGEST_LEN)<0);
-  test_assert(memcmp(cert3->cache_info.identity_digest,
-                     cert1->cache_info.identity_digest,DIGEST_LEN)<0);
   test_same_voter(smartlist_get(con->voters, 1),
                   smartlist_get(v2->voters, 0));
   test_same_voter(smartlist_get(con->voters, 2),
+                  smartlist_get(v1->voters, 0));
+  test_same_voter(smartlist_get(con->voters, 3),
                   smartlist_get(v3->voters, 0));
-  test_same_voter(smartlist_get(con->voters, 3),
-                  smartlist_get(v1->voters, 0));
 
   test_assert(!con->cert);
   test_eq(2, smartlist_len(con->routerstatus_list));
@@ -3412,20 +3413,22 @@
   test_assert(rs->is_valid);
   test_assert(!rs->is_named);
   /* XXXX check version */
+  // x231
+  // x213
 
-  /* Check signatures.  the first voter is pseudo.  The second one hasn't
-     signed.  The third one has signed: validate it. */
+  /* Check signatures.  the first voter is a pseudo-entry with a legacy key.
+   * The second one hasn't signed.  The fourth one has signed: validate it. */
   voter = smartlist_get(con->voters, 1);
   test_assert(!voter->signature);
   test_assert(!voter->good_signature);
   test_assert(!voter->bad_signature);
 
-  voter = smartlist_get(con->voters, 2);
+  voter = smartlist_get(con->voters, 3);
   test_assert(voter->signature);
   test_assert(!voter->good_signature);
   test_assert(!voter->bad_signature);
   test_assert(!networkstatus_check_voter_signature(con,
-                                               smartlist_get(con->voters, 2),
+                                               smartlist_get(con->voters, 3),
                                                cert3));
   test_assert(voter->signature);
   test_assert(voter->good_signature);
@@ -3503,7 +3506,7 @@
                                                smartlist_get(con->voters, 1),
                                                cert2));
     test_assert(!networkstatus_check_voter_signature(con,
-                                               smartlist_get(con->voters, 3),
+                                               smartlist_get(con->voters, 2),
                                                cert1));
 
   }

Modified: tor/trunk/src/or/test_data.c
===================================================================
--- tor/trunk/src/or/test_data.c	2008-12-12 17:36:08 UTC (rev 17609)
+++ tor/trunk/src/or/test_data.c	2008-12-12 18:31:39 UTC (rev 17610)
@@ -8,54 +8,60 @@
 
 const char AUTHORITY_CERT_1[] =
 "dir-key-certificate-version 3\n"
-"fingerprint F810C0CB4974A9C407A8D8F5B0394E3D87BF4794\n"
-"dir-key-published 2007-06-13 16:52:25\n"
-"dir-key-expires 2008-06-13 16:52:25\n"
+"fingerprint D867ACF56A9D229B35C25F0090BC9867E906BE69\n"
+"dir-key-published 2008-12-12 18:07:24\n"
+"dir-key-expires 2009-12-12 18:07:24\n"
 "dir-identity-key\n"
 "-----BEGIN RSA PUBLIC KEY-----\n"
-"MIIBigKCAYEAwqvEOhA+aSNp0JQFd0bZ2OIdamIS6EGVuhOHFkmIS4P2hw99Nkx/\n"
-"YJGXPbHB5uLxMYE539DHKuGztIHOanIqczG8P501F+sGfi1q00rzjYfliGuGnQRQ\n"
-"5+A7Iu6am+KeEP/cnWZt63kiPV2Jt9D8qwlnZTKqMQvnhOz10QCApV0LgFHr/2VO\n"
-"1jEO/Ve+EMO/+fZf8a6graw4ur1foVjLAwUW1fo0QUo0342WSlTA1VouyhZv1LsH\n"
-"LTmA0VFTQnsNnG9V1sPAuqaPDeNntSS3bAWmCAUA6eQS4LF7Pz4OAsRtAurMf98z\n"
-"Pz/thkNa9OBJfLH1zaAmaiUTdEqMNwoT1YHwqav4994tyO7oadV6PdVIAcXD2I4S\n"
-"9tf0NPfaIHwfJPDUY9loKIrGNbrfBLTECrQ3QLNtU3yrYkEyQjcgT8FlBGDcDGqj\n"
-"r8diBPlz+K5iXfl0lIudie4hAFZK+uDu7yQ4y7+N5fVuoBdQDt8S0eMho/PO3Hoe\n"
-"638jhngjy5L5AgMBAAE=\n"
+"MIIBigKCAYEAveMpKlw8oD1YqFqpJchuwSR82BDhutbqgHiez3QO9FmzOctJpV+Y\n"
+"mpTYIJLS/qC+4GBKFF1VK0C4SoBrS3zri0qdXdE+vBGcyrxrjMklpxoqSKRY2011\n"
+"4eqYPghKlo5RzuqteBclGCHyNxWjUJeRKDWgvh+U/gr2uYM6fRm5q0fCzg4aECE7\n"
+"VP6fDGZrMbQI8jHpiMSoC9gkUASNEa6chLInlnP8/H5qUEW4TB9CN/q095pefuwL\n"
+"P+F+1Nz5hnM7fa5XmeMB8iM4RriUmOQlLBZgpQBMpEfWMIPcR9F1Gh3MxERqqUcH\n"
+"tmij+IZdeXg9OkCXykcabaYIhZD3meErn9Tax4oA/THduLfgli9zM0ExwzH1OooN\n"
+"L8rIcJ+2eBo3bQiQUbdYW71sl9w7nSPtircbJUa1mUvWYLPWQxFliPiQSetgJLMj\n"
+"VQqtPmV2hvN2Xk3lLfJO50qMTK7w7Gsaw8UtV4YDM1Hcjp/hQaIB1xfwhXgl+eUU\n"
+"btUa4c+cUTjHAgMBAAE=\n"
 "-----END RSA PUBLIC KEY-----\n"
 "dir-signing-key\n"
 "-----BEGIN RSA PUBLIC KEY-----\n"
-"MIGJAoGBALQJryeKty8evkxsG1xrj3hezAt3qbTSfigptATGdd2CH+VvMKVdY7EM\n"
-"UiiFNuYp3iZTptIKiiUtbmEGUgPsOaL6Ab9aoY80oXWxZ/shBFoIaAjOmn1qNQiA\n"
-"jPNH7YVbJGjZiuJydT+ZuZabqh58ij8mMgdJnflFO7wG39q3QBrdAgMBAAE=\n"
+"MIGJAoGBALPSUInyuEu6NV3NjozplaniIEBzQXEjv1x9/+mqnwZABpYVmuy9A8nx\n"
+"eoyY3sZFsnYwNW/IZjAgG23pEmevu3F+L4myMjjaa6ORl3MgRYQ4gmuFqpefrGdm\n"
+"ywRCleh2JerkQ4VxOuq10dn/abITzLyaZzMw30KXWp5pxKXOLtxFAgMBAAE=\n"
 "-----END RSA PUBLIC KEY-----\n"
+"dir-key-crosscert\n"
+"-----BEGIN ID SIGNATURE-----\n"
+"FTBJNR/Hlt4T53yUMp1r/QCSMCpkHJCbYBT0R0pvYqhqFfYN5qHRSICRXaFFImIF\n"
+"0DGWmwRza6DxPKNzkm5/b7I0de9zJW1jNNdQAQK5xppAtQcAafRdu8cBonnmh9KX\n"
+"k1NrAK/X00FYywju3yl/SxCn1GddVNkHYexEudmJMPM=\n"
+"-----END ID SIGNATURE-----\n"
 "dir-key-certification\n"
 "-----BEGIN SIGNATURE-----\n"
-"Hp6PuryATzAOM0PsmhlxsxTqoxKcI8lv6ti2/4Gnyug4lTx1rPweoZdt4GGttFAe\n"
-"Td9zcUfLUlC0R5eDIlWpR+rxJsRLxuHcVTSr+P0N/Y5xoFzPAqPsVYz6lnvb7vIG\n"
-"9XtixG9jXvVhEqpCZUwoRyPXXwjJoEZE1EuyuvPmlEny8O5thAx1gvZIwUk9hGLU\n"
-"xcErXkajDgfWEGmFWgcs+uk/Sa6n+vjPBwJD9k2hGcoCVZhelU0duCORJaz33twU\n"
-"tebJ/iPMAEkMBIlMvnnr+lKXk548rwE6GHUXWtu/Tho4piV58A0hKAHKpGbVUYEF\n"
-"+11x7n5klsYkUedltrCMajtjB8oawWmRPZZp+sUBmnEtunlCGaBnJNQ3pnCvAalJ\n"
-"yPCSGeQhrW8ZKGWE4aZ8xzyUc5K0zF0KEefPFyHpK61ZDaXr/6TQPz3UF4ndxVjS\n"
-"sxRWj3HyMv6Ax5bASOLgP2ikdXGnZLHau93yKJ6N8U57JjCTavxMlRXONbLS0qYe\n"
+"pjWguLFBfELZDc6DywL6Do21SCl7LcutfpM92MEn4WYeSNcTXNR6lRX7reOEJk4e\n"
+"NwEaMt+Hl7slgeR5wjnW3OmMmRPZK9bquNWbfD+sAOV9bRFZTpXIdleAQFPlwvMF\n"
+"z/Gzwspzn4i2Yh6hySShrctMmW8YL3OM8LsBXzBhp/rG2uHlsxmIsc13DA6HWt61\n"
+"ffY72uNE6KckDGsQ4wPGP9q69y6g+X+TNio1KPbsILbePv6EjbO+rS8FiS4njPlg\n"
+"SPYry1RaUvxzxTkswIzdE1tjJrUiqpbWlTGxrH9N4OszoLm45Pc784KLULrjKIoi\n"
+"Q+vRsGrcMBAa+kDowWU6H1ryKR7KOhzRTcf2uqLE/W3ezaRwmOG+ETmoVFwbhk2X\n"
+"OlbXEM9fWP+INvFkr6Z93VYL2jGkCjV7e3xXmre/Lb92fUcYi6t5dwzfV8gJnIoG\n"
+"eCHd0K8NrQK0ipVk/7zcPDKOPeo9Y5aj/f6X/pDHtb+Dd5sT+l82G/Tqy4DIYUYR\n"
 "-----END SIGNATURE-----\n";
 
 const char AUTHORITY_SIGNKEY_1[] =
 "-----BEGIN RSA PRIVATE KEY-----\n"
-"MIICXAIBAAKBgQC0Ca8nircvHr5MbBtca494XswLd6m00n4oKbQExnXdgh/lbzCl\n"
-"XWOxDFIohTbmKd4mU6bSCoolLW5hBlID7Dmi+gG/WqGPNKF1sWf7IQRaCGgIzpp9\n"
-"ajUIgIzzR+2FWyRo2YricnU/mbmWm6oefIo/JjIHSZ35RTu8Bt/at0Aa3QIDAQAB\n"
-"AoGAKujz+jSxnGVzbbuGeeyY8VOGxmTq6dIRh3kJEupKRVUyTPjHW2J61EPfgRDf\n"
-"GNR5wiDF7eHdMyc026MqAQ1YXv007K9D22cABhe8BivCbibhzUrmcv76vQHIRgp/\n"
-"AbT9fRjhmB/NqjLf6NkBHzx2UAWKbmxcO4pAGSQIY+TnXXECQQDkqTPxUrg2y8kC\n"
-"nvEa2O1yYSCU0cB1EmPaIg0cH5vV/lA/EFbhLIBbA+CUsbX0qxuEBX6B9c36y3AO\n"
-"UOAi7NXnAkEAyZA8rKBIjhHFur9e/U9ApDAjvW1BSy7nDP5GKqw2ayLIt1hfnxZd\n"
-"0YXb53iAsf/YHT/wk4+nBYtQ83xL2U2omwJAfgRaIgcqithoYU9jJR6kTcMFh77J\n"
-"SDvoV9EoVHV/FsJfS0If/1zdKEvMu2XtF3gtY+b7P3hOGod/rAQaYmUPxQJBALz4\n"
-"2JmzsDJaITpDXwg4PE9yvp9DBjs5nu9EmX46dM6fDvUuCoA5VP4x9IigJnA7gF9z\n"
-"6dY+kQWWpu+QcgAqWc8CQDYRUK/qhdbBLdv30CyGrU6Pu0Iij6KZXLGW/zavSDmw\n"
-"4FgbRYYTjukvSs3zUX+52znjYn7wTngIm312A37pHUU=\n"
+"MIICWwIBAAKBgQCz0lCJ8rhLujVdzY6M6ZWp4iBAc0FxI79cff/pqp8GQAaWFZrs\n"
+"vQPJ8XqMmN7GRbJ2MDVvyGYwIBtt6RJnr7txfi+JsjI42mujkZdzIEWEOIJrhaqX\n"
+"n6xnZssEQpXodiXq5EOFcTrqtdHZ/2myE8y8mmczMN9Cl1qeacSlzi7cRQIDAQAB\n"
+"AoGASpzUkDinIbzU0eQt5ugxEnliOnvYRpK3nzAk1JbYPyan1PSIAPz4qn1JBTeV\n"
+"EB3xS7r7ITO8uvFHkFZqLZ2sH1uE6e4sAytJGO+kyqnlkiDTPEXpcGe99j8PH1yj\n"
+"xUOrHRlAYWjG8NEkQi+APA+HZkswE3L/viFwR2AARoE2ac0CQQDsOLdNJa+mqn6N\n"
+"1L76nEl/YgXHtKUks+beOR3IgknKEjcsJJEUHyiu0wjbXZV6gTtyQvcAePglUUD1\n"
+"R2OkOOADAkEAwuCxvHEAPeQbVt8fSvxw74vqew6LITP2Utb1dQK0E26IRPF36BsJ\n"
+"buO/gqMZv6ALq+/KxpA/pUsApbgog9uUFwJAYvHCvbrKX1pM1iXFtP1fv86UMzlU\n"
+"bxI34t8zvXftZonIuGG8rxv6E3hr3k7NvNmCx/KKuZTyA9eMCPFVKEV2dwJACn8j\n"
+"06yagLrqphE6lEVop953cM1lvRIZcHjXm8fbfzhy6pO/C6d5KJnn1NeIKYQrXMV7\n"
+"vJpEc1jI3iQ/Omr3XQJAEBIt5MlP2wlrX9om7B+32XBygUssY3cw/bXybZrtSU0/\n"
+"Yx4lqK0ca5IkTp3HevwnlWaJgbaOTUspCVshzJBhDA==\n"
 "-----END RSA PRIVATE KEY-----\n";
 
 const char AUTHORITY_CERT_2[] =

Modified: tor/trunk/src/tools/tor-gencert.c
===================================================================
--- tor/trunk/src/tools/tor-gencert.c	2008-12-12 17:36:08 UTC (rev 17609)
+++ tor/trunk/src/tools/tor-gencert.c	2008-12-12 18:31:39 UTC (rev 17610)
@@ -394,6 +394,20 @@
   return r;
 }
 
+
+/** Set <b>out</b> to the hex-encoded fingerprint of <b>pkey</b>. */
+static int
+get_digest(EVP_PKEY *pkey, char *out)
+{
+  int r = 1;
+  crypto_pk_env_t *pk = _crypto_new_pk_env_rsa(EVP_PKEY_get1_RSA(pkey));
+  if (pk) {
+    r = crypto_pk_get_digest(pk, out);
+    crypto_free_pk_env(pk);
+  }
+  return r;
+}
+
 /** Generate a new certificate for our loaded or generated keys, and write it
  * to disk.  Return 0 on success, nonzero on failure. */
 static int
@@ -404,6 +418,7 @@
   struct tm tm;
   char published[ISO_TIME_LEN+1];
   char expires[ISO_TIME_LEN+1];
+  char id_digest[DIGEST_LEN];
   char fingerprint[FINGERPRINT_LEN+1];
   char *ident = key_to_string(identity_key);
   char *signing = key_to_string(signing_key);
@@ -414,6 +429,7 @@
   int r;
 
   get_fingerprint(identity_key, fingerprint);
+  get_digest(identity_key, id_digest);
 
   tor_localtime_r(&now, &tm);
   tm.tm_mon += months_lifetime;
@@ -429,12 +445,27 @@
                "dir-key-expires %s\n"
                "dir-identity-key\n%s"
                "dir-signing-key\n%s"
-               "dir-key-certification\n",
+               "dir-key-crosscert\n"
+               "-----BEGIN ID SIGNATURE-----\n",
                address?"\ndir-address ":"", address?address:"",
-               fingerprint, published, expires, ident, signing);
+               fingerprint, published, expires, ident, signing
+               );
   tor_free(ident);
   tor_free(signing);
+
+  /* Append a cross-certification */
+  r = RSA_private_encrypt(DIGEST_LEN, (unsigned char*)id_digest,
+                          (unsigned char*)signature,
+                          EVP_PKEY_get1_RSA(signing_key),
+                          RSA_PKCS1_PADDING);
   signed_len = strlen(buf);
+  base64_encode(buf+signed_len, sizeof(buf)-signed_len, signature, r);
+
+  strlcat(buf,
+          "-----END ID SIGNATURE-----\n"
+          "dir-key-certification\n", sizeof(buf));
+
+  signed_len = strlen(buf);
   SHA1((const unsigned char*)buf,signed_len,(unsigned char*)digest);
 
   r = RSA_private_encrypt(DIGEST_LEN, (unsigned char*)digest,



More information about the tor-commits mailing list