<p>Philipp Deppenwiese has uploaded this change for <strong>review</strong>.</p><p><a href="https://review.coreboot.org/23218">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">security/crypto: Add RSA signature verification support<br><br>* Add core RSA primitives.<br>* Add signature verification based on RSA.<br>* RSA 1024-8192 with PKCS#1.5 padding scheme.<br>* Integrated code from 3rdparty/boot.<br><br>Change-Id: Ic58be92ad184cccaa8d6fc87d2c60bad63f3ec3b<br>Signed-off-by: Philipp Deppenwiese <zaolin@das-labor.org><br>---<br>M src/security/crypto/Kconfig<br>M src/security/crypto/Makefile.inc<br>A src/security/crypto/rsa.h<br>A src/security/crypto/rsa/rsa.c<br>4 files changed, 543 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://review.coreboot.org:29418/coreboot refs/changes/18/23218/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/security/crypto/Kconfig b/src/security/crypto/Kconfig</span><br><span>index b33ff13..4fbb808 100644</span><br><span>--- a/src/security/crypto/Kconfig</span><br><span>+++ b/src/security/crypto/Kconfig</span><br><span>@@ -58,4 +58,14 @@</span><br><span> </span><br><span>       If unsure, say N.</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+config CRYPTO_RSA</span><br><span style="color: hsl(120, 100%, 40%);">+    bool "RSA support"</span><br><span style="color: hsl(120, 100%, 40%);">+  default n</span><br><span style="color: hsl(120, 100%, 40%);">+     select CRYPTO_HASH</span><br><span style="color: hsl(120, 100%, 40%);">+    help</span><br><span style="color: hsl(120, 100%, 40%);">+    Enable this option to to ensure RSA support.</span><br><span style="color: hsl(120, 100%, 40%);">+          Currently only signature verification with PKCS#1.5 is supported.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   If unsure, say N.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> endmenu # Cryptographic Primitives</span><br><span>diff --git a/src/security/crypto/Makefile.inc b/src/security/crypto/Makefile.inc</span><br><span>index b22ce00..d4e4b1b 100644</span><br><span>--- a/src/security/crypto/Makefile.inc</span><br><span>+++ b/src/security/crypto/Makefile.inc</span><br><span>@@ -24,3 +24,8 @@</span><br><span> romstage-$(CONFIG_CRYPTO_HMAC) += hmac/hmac.c</span><br><span> ramstage-$(CONFIG_CRYPTO_HMAC) += hmac/hmac.c</span><br><span> smm-$(CONFIG_CRYPTO_HMAC) += hmac/hmac.c</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+verstage-$(CONFIG_CRYPTO_RSA) += rsa/rsa.c common/common.c</span><br><span style="color: hsl(120, 100%, 40%);">+romstage-$(CONFIG_CRYPTO_RSA) += rsa/rsa.c common/common.c</span><br><span style="color: hsl(120, 100%, 40%);">+ramstage-$(CONFIG_CRYPTO_RSA) += rsa/rsa.c common/common.c</span><br><span style="color: hsl(120, 100%, 40%);">+smm-$(CONFIG_CRYPTO_RSA) += rsa/rsa.c common/common.c</span><br><span>diff --git a/src/security/crypto/rsa.h b/src/security/crypto/rsa.h</span><br><span>new file mode 100644</span><br><span>index 0000000..543c8eb</span><br><span>--- /dev/null</span><br><span>+++ b/src/security/crypto/rsa.h</span><br><span>@@ -0,0 +1,102 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Use of this source code is governed by a BSD-style license that can be</span><br><span style="color: hsl(120, 100%, 40%);">+ * found in the LICENSE file.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef CRYPTO_RSA_H_</span><br><span style="color: hsl(120, 100%, 40%);">+#define CRYPTO_RSA_H_</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <security/crypto/hash.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct workbuf;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+enum signature_algorithm {</span><br><span style="color: hsl(120, 100%, 40%);">+    /* Invalid or unsupported signature type */</span><br><span style="color: hsl(120, 100%, 40%);">+   SIG_INVALID = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /*</span><br><span style="color: hsl(120, 100%, 40%);">+     * No signature algorithm.  The digest is unsigned.  See</span><br><span style="color: hsl(120, 100%, 40%);">+       * ID_NONE_* for key IDs to use with this algorithm.</span><br><span style="color: hsl(120, 100%, 40%);">+   */</span><br><span style="color: hsl(120, 100%, 40%);">+   SIG_NONE = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       /* RSA algorithms of the given length in bits (1024-8192) */</span><br><span style="color: hsl(120, 100%, 40%);">+  SIG_RSA1024 = 2,  /* Warning!  This is likely to be deprecated! */</span><br><span style="color: hsl(120, 100%, 40%);">+    SIG_RSA2048 = 3,</span><br><span style="color: hsl(120, 100%, 40%);">+      SIG_RSA4096 = 4,</span><br><span style="color: hsl(120, 100%, 40%);">+      SIG_RSA8192 = 5,</span><br><span style="color: hsl(120, 100%, 40%);">+      SIG_RSA2048_EXP3 = 6,</span><br><span style="color: hsl(120, 100%, 40%);">+ SIG_RSA3072_EXP3 = 7,</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       /* Last index. Don't add anything below. */</span><br><span style="color: hsl(120, 100%, 40%);">+       SIG_ALG_COUNT,</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Public key structure in RAM */</span><br><span style="color: hsl(120, 100%, 40%);">+struct public_key {</span><br><span style="color: hsl(120, 100%, 40%);">+        uint32_t arrsize;    /* Length of n[] and rr[] in number of uint32_t */</span><br><span style="color: hsl(120, 100%, 40%);">+       uint32_t n0inv;      /* -1 / n[0] mod 2^32 */</span><br><span style="color: hsl(120, 100%, 40%);">+ const uint32_t *n;   /* Modulus as little endian array */</span><br><span style="color: hsl(120, 100%, 40%);">+     const uint32_t *rr;  /* R^2 as little endian array */</span><br><span style="color: hsl(120, 100%, 40%);">+ enum signature_algorithm sig_alg;       /* Signature algorithm */</span><br><span style="color: hsl(120, 100%, 40%);">+     enum hash_algorithm hash_alg;   /* Hash algorithm */</span><br><span style="color: hsl(120, 100%, 40%);">+  const char *desc;                       /* Description */</span><br><span style="color: hsl(120, 100%, 40%);">+     uint32_t version;                       /* Key version */</span><br><span style="color: hsl(120, 100%, 40%);">+     const struct id *id;            /* Key ID */</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * Convert crypto_algorithm to signature_algorithm.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param algorithm   Crypto algorithm (crypto_algorithm)</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @return The signature algorithm for that crypto algorithm, or</span><br><span style="color: hsl(120, 100%, 40%);">+ * SIG_INVALID if the crypto algorithm or its corresponding signature</span><br><span style="color: hsl(120, 100%, 40%);">+ * algorithm is invalid or not supported.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+enum signature_algorithm crypto_to_signature(uint32_t algorithm);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * Return the size of a RSA signature</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param sig_alg        Signature algorithm</span><br><span style="color: hsl(120, 100%, 40%);">+ * @return The size of the signature in bytes, or 0 if error.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+uint32_t rsa_sig_size(enum signature_algorithm sig_alg);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * Return the size of a pre-processed RSA public key.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param sig_alg  Signature algorithm</span><br><span style="color: hsl(120, 100%, 40%);">+ * @return The size of the preprocessed key in bytes, or 0 if error.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+uint32_t packed_key_size(enum signature_algorithm sig_alg);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * Check pkcs 1.5 padding bytes</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param sig          Signature to verify</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param key              Key to take signature and hash algorithms from</span><br><span style="color: hsl(120, 100%, 40%);">+ * @return SUCCESS, or non-zero if error.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int check_padding(const uint8_t *sig, const struct public_key *key);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Size of work buffer sufficient for rsa_verify_digest() worst case */</span><br><span style="color: hsl(120, 100%, 40%);">+#define VERIFY_RSA_DIGEST_WORKBUF_BYTES (3 * 1024)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * Verify a RSA PKCS1.5 signature against an expected hash digest.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param key               Key to use in signature verification</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param sig             Signature to verify (destroyed in process)</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param digest    Digest of signed data</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param wb             Work buffer</span><br><span style="color: hsl(120, 100%, 40%);">+ * @return SUCCESS, or non-zero if error.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int rsa_verify_digest(const struct public_key *key,</span><br><span style="color: hsl(120, 100%, 40%);">+                        uint8_t *sig,</span><br><span style="color: hsl(120, 100%, 40%);">+                         const uint8_t *digest,</span><br><span style="color: hsl(120, 100%, 40%);">+                        const struct workbuf *wb);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#endif  /* CRYPTO_RSA_H_ */</span><br><span>diff --git a/src/security/crypto/rsa/rsa.c b/src/security/crypto/rsa/rsa.c</span><br><span>new file mode 100644</span><br><span>index 0000000..5e53b3c</span><br><span>--- /dev/null</span><br><span>+++ b/src/security/crypto/rsa/rsa.c</span><br><span>@@ -0,0 +1,426 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Use of this source code is governed by a BSD-style license that can be</span><br><span style="color: hsl(120, 100%, 40%);">+ * found in the LICENSE file.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Implementation of RSA signature verification which uses a pre-processed key</span><br><span style="color: hsl(120, 100%, 40%);">+ * for computation. The code extends Android's RSA verification code to support</span><br><span style="color: hsl(120, 100%, 40%);">+ * multiple RSA key lengths and hash digest algorithms.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <console/console.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <security/crypto/rsa.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <security/crypto/errors.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <security/crypto/common.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * a[] -= mod</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static void subM(const struct public_key *key, uint32_t *a)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      int64_t A = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+        uint32_t i;</span><br><span style="color: hsl(120, 100%, 40%);">+   for (i = 0; i < key->arrsize; ++i) {</span><br><span style="color: hsl(120, 100%, 40%);">+            A += (uint64_t)a[i] - key->n[i];</span><br><span style="color: hsl(120, 100%, 40%);">+           a[i] = (uint32_t)A;</span><br><span style="color: hsl(120, 100%, 40%);">+           A >>= 32;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * Return a[] >= mod</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static int mont_ge(const struct public_key *key, uint32_t *a)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   uint32_t i;</span><br><span style="color: hsl(120, 100%, 40%);">+   for (i = key->arrsize; i;) {</span><br><span style="color: hsl(120, 100%, 40%);">+               --i;</span><br><span style="color: hsl(120, 100%, 40%);">+          if (a[i] < key->n[i])</span><br><span style="color: hsl(120, 100%, 40%);">+                   return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+             if (a[i] > key->n[i])</span><br><span style="color: hsl(120, 100%, 40%);">+                   return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+     return 1;  /* equal */</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * Montgomery c[] += a * b[] / R % mod</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static void montMulAdd(const struct public_key *key,</span><br><span style="color: hsl(120, 100%, 40%);">+                       uint32_t *c,</span><br><span style="color: hsl(120, 100%, 40%);">+                       const uint32_t a,</span><br><span style="color: hsl(120, 100%, 40%);">+                       const uint32_t *b)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      uint64_t A = (uint64_t)a * b[0] + c[0];</span><br><span style="color: hsl(120, 100%, 40%);">+       uint32_t d0 = (uint32_t)A * key->n0inv;</span><br><span style="color: hsl(120, 100%, 40%);">+    uint64_t B = (uint64_t)d0 * key->n[0] + (uint32_t)A;</span><br><span style="color: hsl(120, 100%, 40%);">+       uint32_t i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = 1; i < key->arrsize; ++i) {</span><br><span style="color: hsl(120, 100%, 40%);">+            A = (A >> 32) + (uint64_t)a * b[i] + c[i];</span><br><span style="color: hsl(120, 100%, 40%);">+              B = (B >> 32) + (uint64_t)d0 * key->n[i] + (uint32_t)A;</span><br><span style="color: hsl(120, 100%, 40%);">+              c[i - 1] = (uint32_t)B;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   A = (A >> 32) + (B >> 32);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      c[i - 1] = (uint32_t)A;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     if (A >> 32) {</span><br><span style="color: hsl(120, 100%, 40%);">+          subM(key, c);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * Montgomery c[] += 0 * b[] / R % mod</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static void montMulAdd0(const struct public_key *key,</span><br><span style="color: hsl(120, 100%, 40%);">+                       uint32_t *c,</span><br><span style="color: hsl(120, 100%, 40%);">+                  const uint32_t *b)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t d0 = c[0] * key->n0inv;</span><br><span style="color: hsl(120, 100%, 40%);">+   uint64_t B = (uint64_t)d0 * key->n[0] + c[0];</span><br><span style="color: hsl(120, 100%, 40%);">+      uint32_t i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = 1; i < key->arrsize; ++i) {</span><br><span style="color: hsl(120, 100%, 40%);">+            B = (B >> 32) + (uint64_t)d0 * key->n[i] + c[i];</span><br><span style="color: hsl(120, 100%, 40%);">+             c[i - 1] = (uint32_t)B;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   c[i - 1] = B >> 32;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * Montgomery c[] = a[] * b[] / R % mod</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static void montMul(const struct public_key *key,</span><br><span style="color: hsl(120, 100%, 40%);">+                    uint32_t *c,</span><br><span style="color: hsl(120, 100%, 40%);">+                    const uint32_t *a,</span><br><span style="color: hsl(120, 100%, 40%);">+                    const uint32_t *b)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     uint32_t i;</span><br><span style="color: hsl(120, 100%, 40%);">+   for (i = 0; i < key->arrsize; ++i) {</span><br><span style="color: hsl(120, 100%, 40%);">+            c[i] = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+     for (i = 0; i < key->arrsize; ++i) {</span><br><span style="color: hsl(120, 100%, 40%);">+            montMulAdd(key, c, a[i], b);</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Montgomery c[] = a[] * 1 / R % key. */</span><br><span style="color: hsl(120, 100%, 40%);">+static void montMul1(const struct public_key *key,</span><br><span style="color: hsl(120, 100%, 40%);">+              uint32_t *c,</span><br><span style="color: hsl(120, 100%, 40%);">+                  const uint32_t *a)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    int i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      for (i = 0; i < key->arrsize; ++i)</span><br><span style="color: hsl(120, 100%, 40%);">+              c[i] = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   montMulAdd(key, c, 1, a);</span><br><span style="color: hsl(120, 100%, 40%);">+     for (i = 1; i < key->arrsize; ++i)</span><br><span style="color: hsl(120, 100%, 40%);">+              montMulAdd0(key, c, a);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * In-place public exponentiation.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param key                Key to use in signing</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param inout          Input and output big-endian byte array</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param workbuf32     Work buffer; caller must verify this is</span><br><span style="color: hsl(120, 100%, 40%);">+ *                     (3 * key->arrsize) elements long.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param exp             RSA public exponent: either 65537 (F4) or 3</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static void modpow(const struct public_key *key, uint8_t *inout,</span><br><span style="color: hsl(120, 100%, 40%);">+            uint32_t *workbuf32, int exp)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      uint32_t *a = workbuf32;</span><br><span style="color: hsl(120, 100%, 40%);">+      uint32_t *aR = a + key->arrsize;</span><br><span style="color: hsl(120, 100%, 40%);">+   uint32_t *aaR = aR + key->arrsize;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t *aaa = aaR;  /* Re-use location. */</span><br><span style="color: hsl(120, 100%, 40%);">+  int i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* Convert from big endian byte array to little endian word array. */</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = 0; i < (int)key->arrsize; ++i) {</span><br><span style="color: hsl(120, 100%, 40%);">+               uint32_t tmp =</span><br><span style="color: hsl(120, 100%, 40%);">+                        (inout[((key->arrsize - 1 - i) * 4) + 0] << 24) |</span><br><span style="color: hsl(120, 100%, 40%);">+                    (inout[((key->arrsize - 1 - i) * 4) + 1] << 16) |</span><br><span style="color: hsl(120, 100%, 40%);">+                    (inout[((key->arrsize - 1 - i) * 4) + 2] << 8) |</span><br><span style="color: hsl(120, 100%, 40%);">+                     (inout[((key->arrsize - 1 - i) * 4) + 3] << 0);</span><br><span style="color: hsl(120, 100%, 40%);">+              a[i] = tmp;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   montMul(key, aR, a, key->rr);  /* aR = a * RR / R mod M   */</span><br><span style="color: hsl(120, 100%, 40%);">+       if (exp == 3) {</span><br><span style="color: hsl(120, 100%, 40%);">+               montMul(key, aaR, aR, aR); /* aaR = aR * aR / R mod M */</span><br><span style="color: hsl(120, 100%, 40%);">+              montMul(key, a, aaR, aR); /* a = aaR * aR / R mod M */</span><br><span style="color: hsl(120, 100%, 40%);">+                montMul1(key, aaa, a); /* aaa = a * 1 / R mod M */</span><br><span style="color: hsl(120, 100%, 40%);">+    } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              /* Exponent 65537 */</span><br><span style="color: hsl(120, 100%, 40%);">+          for (i = 0; i < 16; i+=2) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        montMul(key, aaR, aR, aR);  /* aaR = aR * aR / R mod M */</span><br><span style="color: hsl(120, 100%, 40%);">+                     montMul(key, aR, aaR, aaR);  /* aR = aaR * aaR / R mod M */</span><br><span style="color: hsl(120, 100%, 40%);">+           }</span><br><span style="color: hsl(120, 100%, 40%);">+             montMul(key, aaa, aR, a);  /* aaa = aR * a / R mod M */</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Make sure aaa < mod; aaa is at most 1x mod too large. */</span><br><span style="color: hsl(120, 100%, 40%);">+        if (mont_ge(key, aaa)) {</span><br><span style="color: hsl(120, 100%, 40%);">+              subM(key, aaa);</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Convert to bigendian byte array */</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = (int)key->arrsize - 1; i >= 0; --i) {</span><br><span style="color: hsl(120, 100%, 40%);">+          uint32_t tmp = aaa[i];</span><br><span style="color: hsl(120, 100%, 40%);">+                *inout++ = (uint8_t)(tmp >> 24);</span><br><span style="color: hsl(120, 100%, 40%);">+                *inout++ = (uint8_t)(tmp >> 16);</span><br><span style="color: hsl(120, 100%, 40%);">+                *inout++ = (uint8_t)(tmp >>  8);</span><br><span style="color: hsl(120, 100%, 40%);">+                *inout++ = (uint8_t)(tmp >>  0);</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static const uint8_t crypto_to_sig[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+    SIG_RSA1024,</span><br><span style="color: hsl(120, 100%, 40%);">+  SIG_RSA1024,</span><br><span style="color: hsl(120, 100%, 40%);">+  SIG_RSA1024,</span><br><span style="color: hsl(120, 100%, 40%);">+  SIG_RSA2048,</span><br><span style="color: hsl(120, 100%, 40%);">+  SIG_RSA2048,</span><br><span style="color: hsl(120, 100%, 40%);">+  SIG_RSA2048,</span><br><span style="color: hsl(120, 100%, 40%);">+  SIG_RSA4096,</span><br><span style="color: hsl(120, 100%, 40%);">+  SIG_RSA4096,</span><br><span style="color: hsl(120, 100%, 40%);">+  SIG_RSA4096,</span><br><span style="color: hsl(120, 100%, 40%);">+  SIG_RSA8192,</span><br><span style="color: hsl(120, 100%, 40%);">+  SIG_RSA8192,</span><br><span style="color: hsl(120, 100%, 40%);">+  SIG_RSA8192,</span><br><span style="color: hsl(120, 100%, 40%);">+  SIG_RSA2048_EXP3,</span><br><span style="color: hsl(120, 100%, 40%);">+     SIG_RSA2048_EXP3,</span><br><span style="color: hsl(120, 100%, 40%);">+     SIG_RSA2048_EXP3,</span><br><span style="color: hsl(120, 100%, 40%);">+     SIG_RSA3072_EXP3,</span><br><span style="color: hsl(120, 100%, 40%);">+     SIG_RSA3072_EXP3,</span><br><span style="color: hsl(120, 100%, 40%);">+     SIG_RSA3072_EXP3,</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * Convert crypto_algorithm to signature_algorithm.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param algorithm      Crypto algorithm (crypto_algorithm)</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @return The signature algorithm for that crypto algorithm, or</span><br><span style="color: hsl(120, 100%, 40%);">+ * SIG_INVALID if the crypto algorithm or its corresponding signature</span><br><span style="color: hsl(120, 100%, 40%);">+ * algorithm is invalid or not supported.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+enum signature_algorithm crypto_to_signature(uint32_t algorithm)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (algorithm < ARRAY_SIZE(crypto_to_sig))</span><br><span style="color: hsl(120, 100%, 40%);">+         return crypto_to_sig[algorithm];</span><br><span style="color: hsl(120, 100%, 40%);">+      else</span><br><span style="color: hsl(120, 100%, 40%);">+          return SIG_INVALID;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+uint32_t rsa_sig_size(enum signature_algorithm sig_alg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  switch (sig_alg) {</span><br><span style="color: hsl(120, 100%, 40%);">+    case SIG_RSA1024:</span><br><span style="color: hsl(120, 100%, 40%);">+             return 1024 / 8;</span><br><span style="color: hsl(120, 100%, 40%);">+      case SIG_RSA2048:</span><br><span style="color: hsl(120, 100%, 40%);">+     case SIG_RSA2048_EXP3:</span><br><span style="color: hsl(120, 100%, 40%);">+                return 2048 / 8;</span><br><span style="color: hsl(120, 100%, 40%);">+      case SIG_RSA3072_EXP3:</span><br><span style="color: hsl(120, 100%, 40%);">+                return 3072 / 8;</span><br><span style="color: hsl(120, 100%, 40%);">+      case SIG_RSA4096:</span><br><span style="color: hsl(120, 100%, 40%);">+             return 4096 / 8;</span><br><span style="color: hsl(120, 100%, 40%);">+      case SIG_RSA8192:</span><br><span style="color: hsl(120, 100%, 40%);">+             return 8192 / 8;</span><br><span style="color: hsl(120, 100%, 40%);">+      default:</span><br><span style="color: hsl(120, 100%, 40%);">+              return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/**</span><br><span style="color: hsl(120, 100%, 40%);">+ * Return the exponent used by an RSA algorithm</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param sig_alg     Signature algorithm</span><br><span style="color: hsl(120, 100%, 40%);">+ * @return The exponent to use (3 or 65537(F4)), or 0 if error.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static uint32_t rsa_exponent(enum signature_algorithm sig_alg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  switch (sig_alg) {</span><br><span style="color: hsl(120, 100%, 40%);">+    case SIG_RSA1024:</span><br><span style="color: hsl(120, 100%, 40%);">+     case SIG_RSA2048:</span><br><span style="color: hsl(120, 100%, 40%);">+     case SIG_RSA4096:</span><br><span style="color: hsl(120, 100%, 40%);">+     case SIG_RSA8192:</span><br><span style="color: hsl(120, 100%, 40%);">+             return 65537;</span><br><span style="color: hsl(120, 100%, 40%);">+ case SIG_RSA2048_EXP3:</span><br><span style="color: hsl(120, 100%, 40%);">+        case SIG_RSA3072_EXP3:</span><br><span style="color: hsl(120, 100%, 40%);">+                return 3;</span><br><span style="color: hsl(120, 100%, 40%);">+     default:</span><br><span style="color: hsl(120, 100%, 40%);">+              return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+uint32_t packed_key_size(enum signature_algorithm sig_alg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t sig_size = rsa_sig_size(sig_alg);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!sig_size)</span><br><span style="color: hsl(120, 100%, 40%);">+                return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /*</span><br><span style="color: hsl(120, 100%, 40%);">+     * Total size needed by a RSAPublicKey buffer is =</span><br><span style="color: hsl(120, 100%, 40%);">+     *  2 * key_len bytes for the n and rr arrays</span><br><span style="color: hsl(120, 100%, 40%);">+  *  + sizeof len + sizeof n0inv.</span><br><span style="color: hsl(120, 100%, 40%);">+       */</span><br><span style="color: hsl(120, 100%, 40%);">+   return 2 * sig_size + 2 * sizeof(uint32_t);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * PKCS 1.5 padding (from the RSA PKCS#1 v2.1 standard)</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Depending on the RSA key size and hash function, the padding is calculated</span><br><span style="color: hsl(120, 100%, 40%);">+ * as follows:</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * 0x00 || 0x01 || PS || 0x00 || T</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * T: DER Encoded DigestInfo value which depends on the hash function used.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * SHA-1:   (0x)30 21 30 09 06 05 2b 0e 03 02 1a 05 00 04 14 || H.</span><br><span style="color: hsl(120, 100%, 40%);">+ * SHA-256: (0x)30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20 || H.</span><br><span style="color: hsl(120, 100%, 40%);">+ * SHA-512: (0x)30 51 30 0d 06 09 60 86 48 01 65 03 04 02 03 05 00 04 40 || H.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Length(T) = 35 octets for SHA-1</span><br><span style="color: hsl(120, 100%, 40%);">+ * Length(T) = 51 octets for SHA-256</span><br><span style="color: hsl(120, 100%, 40%);">+ * Length(T) = 83 octets for SHA-512</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * PS: octet string consisting of {Length(RSA Key) - Length(T) - 3} 0xFF</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static const uint8_t sha1_tail[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+        0x00,0x30,0x21,0x30,0x09,0x06,0x05,0x2b,</span><br><span style="color: hsl(120, 100%, 40%);">+      0x0e,0x03,0x02,0x1a,0x05,0x00,0x04,0x14</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static const uint8_t sha256_tail[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+ 0x00,0x30,0x31,0x30,0x0d,0x06,0x09,0x60,</span><br><span style="color: hsl(120, 100%, 40%);">+      0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,</span><br><span style="color: hsl(120, 100%, 40%);">+      0x05,0x00,0x04,0x20</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static const uint8_t sha512_tail[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+     0x00,0x30,0x51,0x30,0x0d,0x06,0x09,0x60,</span><br><span style="color: hsl(120, 100%, 40%);">+      0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,</span><br><span style="color: hsl(120, 100%, 40%);">+      0x05,0x00,0x04,0x40</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int check_padding(const uint8_t *sig, const struct public_key *key)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     /* Determine padding to use depending on the signature type */</span><br><span style="color: hsl(120, 100%, 40%);">+        uint32_t sig_size = rsa_sig_size(key->sig_alg);</span><br><span style="color: hsl(120, 100%, 40%);">+    uint32_t hash_size = digest_size(key->hash_alg);</span><br><span style="color: hsl(120, 100%, 40%);">+   uint32_t pad_size = sig_size - hash_size;</span><br><span style="color: hsl(120, 100%, 40%);">+     const uint8_t *tail;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint32_t tail_size;</span><br><span style="color: hsl(120, 100%, 40%);">+   int result = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+       int i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      if (!sig_size || !hash_size || hash_size > sig_size)</span><br><span style="color: hsl(120, 100%, 40%);">+               return ERROR_RSA_PADDING_SIZE;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      switch (key->hash_alg) {</span><br><span style="color: hsl(120, 100%, 40%);">+   case HASH_SHA1:</span><br><span style="color: hsl(120, 100%, 40%);">+               tail = sha1_tail;</span><br><span style="color: hsl(120, 100%, 40%);">+             tail_size = sizeof(sha1_tail);</span><br><span style="color: hsl(120, 100%, 40%);">+                break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case HASH_SHA256:</span><br><span style="color: hsl(120, 100%, 40%);">+             tail = sha256_tail;</span><br><span style="color: hsl(120, 100%, 40%);">+           tail_size = sizeof(sha256_tail);</span><br><span style="color: hsl(120, 100%, 40%);">+              break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case HASH_SHA512:</span><br><span style="color: hsl(120, 100%, 40%);">+             tail = sha512_tail;</span><br><span style="color: hsl(120, 100%, 40%);">+           tail_size = sizeof(sha512_tail);</span><br><span style="color: hsl(120, 100%, 40%);">+              break;</span><br><span style="color: hsl(120, 100%, 40%);">+        default:</span><br><span style="color: hsl(120, 100%, 40%);">+              return ERROR_RSA_PADDING_ALGORITHM;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* First 2 bytes are always 0x00 0x01 */</span><br><span style="color: hsl(120, 100%, 40%);">+      result |= *sig++ ^ 0x00;</span><br><span style="color: hsl(120, 100%, 40%);">+      result |= *sig++ ^ 0x01;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* Then 0xff bytes until the tail */</span><br><span style="color: hsl(120, 100%, 40%);">+  for (i = 0; i < pad_size - tail_size - 2; i++)</span><br><span style="color: hsl(120, 100%, 40%);">+             result |= *sig++ ^ 0xff;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /*</span><br><span style="color: hsl(120, 100%, 40%);">+     * Then the tail.  Even though there are probably no timing issues</span><br><span style="color: hsl(120, 100%, 40%);">+     * here, we use safe_memcmp() just to be on the safe side.</span><br><span style="color: hsl(120, 100%, 40%);">+     */</span><br><span style="color: hsl(120, 100%, 40%);">+   result |= safe_memcmp(sig, tail, tail_size);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        return result ? ERROR_RSA_PADDING : SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int rsa_verify_digest(const struct public_key *key,</span><br><span style="color: hsl(120, 100%, 40%);">+                          uint8_t *sig,</span><br><span style="color: hsl(120, 100%, 40%);">+                         const uint8_t *digest,</span><br><span style="color: hsl(120, 100%, 40%);">+                        const struct workbuf *wb)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        struct workbuf wblocal = *wb;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t *workbuf32;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint32_t key_bytes;</span><br><span style="color: hsl(120, 100%, 40%);">+   int sig_size;</span><br><span style="color: hsl(120, 100%, 40%);">+ int pad_size;</span><br><span style="color: hsl(120, 100%, 40%);">+ int exp;</span><br><span style="color: hsl(120, 100%, 40%);">+      int rv;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!key || !sig || !digest)</span><br><span style="color: hsl(120, 100%, 40%);">+          return ERROR_RSA_VERIFY_PARAM;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      sig_size = rsa_sig_size(key->sig_alg);</span><br><span style="color: hsl(120, 100%, 40%);">+     exp = rsa_exponent(key->sig_alg);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!sig_size || !exp) {</span><br><span style="color: hsl(120, 100%, 40%);">+              printk(BIOS_DEBUG,"Invalid signature type!\n");</span><br><span style="color: hsl(120, 100%, 40%);">+             return ERROR_RSA_VERIFY_ALGORITHM;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Signature length should be same as key length */</span><br><span style="color: hsl(120, 100%, 40%);">+   key_bytes = key->arrsize * sizeof(uint32_t);</span><br><span style="color: hsl(120, 100%, 40%);">+       if (key_bytes != sig_size) {</span><br><span style="color: hsl(120, 100%, 40%);">+          printk(BIOS_DEBUG,"Signature is of incorrect length!\n");</span><br><span style="color: hsl(120, 100%, 40%);">+           return ERROR_RSA_VERIFY_SIG_LEN;</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   workbuf32 = workbuf_alloc(&wblocal, 3 * key_bytes);</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!workbuf32) {</span><br><span style="color: hsl(120, 100%, 40%);">+             printk(BIOS_DEBUG,"ERROR - vboot2 work buffer too small!\n");</span><br><span style="color: hsl(120, 100%, 40%);">+               return ERROR_RSA_VERIFY_WORKBUF;</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   modpow(key, sig, workbuf32, exp);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   workbuf_free(&wblocal, 3 * key_bytes);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /*</span><br><span style="color: hsl(120, 100%, 40%);">+     * Check padding.  Only fail immediately if the padding size is bad.</span><br><span style="color: hsl(120, 100%, 40%);">+   * Otherwise, continue on to check the digest to reduce the risk of</span><br><span style="color: hsl(120, 100%, 40%);">+    * timing based attacks.</span><br><span style="color: hsl(120, 100%, 40%);">+       */</span><br><span style="color: hsl(120, 100%, 40%);">+   rv = check_padding(sig, key);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rv == ERROR_RSA_PADDING_SIZE)</span><br><span style="color: hsl(120, 100%, 40%);">+             return rv;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /*</span><br><span style="color: hsl(120, 100%, 40%);">+     * Check digest.  Even though there are probably no timing issues here,</span><br><span style="color: hsl(120, 100%, 40%);">+        * use safe_memcmp() just to be on the safe side.  (That's also why</span><br><span style="color: hsl(120, 100%, 40%);">+        * we don't return before this check if the padding check failed.)</span><br><span style="color: hsl(120, 100%, 40%);">+         */</span><br><span style="color: hsl(120, 100%, 40%);">+   pad_size = sig_size - digest_size(key->hash_alg);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (safe_memcmp(sig + pad_size, digest, key_bytes - pad_size)) {</span><br><span style="color: hsl(120, 100%, 40%);">+              printk(BIOS_DEBUG,"Digest check failed!\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                if (!rv)</span><br><span style="color: hsl(120, 100%, 40%);">+                      rv = ERROR_RSA_VERIFY_DIGEST;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return rv;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span></span><br></pre><p>To view, visit <a href="https://review.coreboot.org/23218">change 23218</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://review.coreboot.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://review.coreboot.org/23218"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: coreboot </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: Ic58be92ad184cccaa8d6fc87d2c60bad63f3ec3b </div>
<div style="display:none"> Gerrit-Change-Number: 23218 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Philipp Deppenwiese <zaolin.daisuki@gmail.com> </div>