summaryrefslogtreecommitdiff
path: root/src/common/crypto_rsa.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/crypto_rsa.c')
-rw-r--r--src/common/crypto_rsa.c116
1 files changed, 116 insertions, 0 deletions
diff --git a/src/common/crypto_rsa.c b/src/common/crypto_rsa.c
index 2090b2e65f..d269d28f30 100644
--- a/src/common/crypto_rsa.c
+++ b/src/common/crypto_rsa.c
@@ -850,6 +850,122 @@ crypto_pk_get_hashed_fingerprint(crypto_pk_t *pk, char *fp_out)
return 0;
}
+/** Check a siglen-byte long signature at <b>sig</b> against
+ * <b>datalen</b> bytes of data at <b>data</b>, using the public key
+ * in <b>env</b>. Return 0 if <b>sig</b> is a correct signature for
+ * SHA1(data). Else return -1.
+ */
+MOCK_IMPL(int,
+crypto_pk_public_checksig_digest,(crypto_pk_t *env, const char *data,
+ size_t datalen, const char *sig,
+ size_t siglen))
+{
+ char digest[DIGEST_LEN];
+ char *buf;
+ size_t buflen;
+ int r;
+
+ tor_assert(env);
+ tor_assert(data);
+ tor_assert(sig);
+ tor_assert(datalen < SIZE_T_CEILING);
+ tor_assert(siglen < SIZE_T_CEILING);
+
+ if (crypto_digest(digest,data,datalen)<0) {
+ log_warn(LD_BUG, "couldn't compute digest");
+ return -1;
+ }
+ buflen = crypto_pk_keysize(env);
+ buf = tor_malloc(buflen);
+ r = crypto_pk_public_checksig(env,buf,buflen,sig,siglen);
+ if (r != DIGEST_LEN) {
+ log_warn(LD_CRYPTO, "Invalid signature");
+ tor_free(buf);
+ return -1;
+ }
+ if (tor_memneq(buf, digest, DIGEST_LEN)) {
+ log_warn(LD_CRYPTO, "Signature mismatched with digest.");
+ tor_free(buf);
+ return -1;
+ }
+ tor_free(buf);
+
+ return 0;
+}
+
+/** Compute a SHA1 digest of <b>fromlen</b> bytes of data stored at
+ * <b>from</b>; sign the data with the private key in <b>env</b>, and
+ * store it in <b>to</b>. Return the number of bytes written on
+ * success, and -1 on failure.
+ *
+ * <b>tolen</b> is the number of writable bytes in <b>to</b>, and must be
+ * at least the length of the modulus of <b>env</b>.
+ */
+int
+crypto_pk_private_sign_digest(crypto_pk_t *env, char *to, size_t tolen,
+ const char *from, size_t fromlen)
+{
+ int r;
+ char digest[DIGEST_LEN];
+ if (crypto_digest(digest,from,fromlen)<0)
+ return -1;
+ r = crypto_pk_private_sign(env,to,tolen,digest,DIGEST_LEN);
+ memwipe(digest, 0, sizeof(digest));
+ return r;
+}
+
+/** Given a private or public key <b>pk</b>, put a SHA1 hash of the
+ * public key into <b>digest_out</b> (must have DIGEST_LEN bytes of space).
+ * Return 0 on success, -1 on failure.
+ */
+int
+crypto_pk_get_digest(const crypto_pk_t *pk, char *digest_out)
+{
+ char *buf;
+ size_t buflen;
+ int len;
+ int rv = -1;
+
+ buflen = crypto_pk_keysize(pk)*2;
+ buf = tor_malloc(buflen);
+ len = crypto_pk_asn1_encode(pk, buf, buflen);
+ if (len < 0)
+ goto done;
+
+ if (crypto_digest(digest_out, buf, len) < 0)
+ goto done;
+
+ rv = 0;
+ done:
+ tor_free(buf);
+ return rv;
+}
+
+/** Compute all digests of the DER encoding of <b>pk</b>, and store them
+ * in <b>digests_out</b>. Return 0 on success, -1 on failure. */
+int
+crypto_pk_get_common_digests(crypto_pk_t *pk, common_digests_t *digests_out)
+{
+ char *buf;
+ size_t buflen;
+ int len;
+ int rv = -1;
+
+ buflen = crypto_pk_keysize(pk)*2;
+ buf = tor_malloc(buflen);
+ len = crypto_pk_asn1_encode(pk, buf, buflen);
+ if (len < 0)
+ goto done;
+
+ if (crypto_common_digests(digests_out, (char*)buf, len) < 0)
+ goto done;
+
+ rv = 0;
+ done:
+ tor_free(buf);
+ return rv;
+}
+
/** Given a crypto_pk_t <b>pk</b>, allocate a new buffer containing the
* Base64 encoding of the DER representation of the private key as a NUL
* terminated string, and return it via <b>priv_out</b>. Return 0 on