summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSumit Bose <sbose@redhat.com>2016-06-15 21:49:02 +0200
committerJakub Hrozek <jhrozek@redhat.com>2016-07-07 18:13:32 +0200
commit8b2bd0587af6ed6bbd7eab7a332ec88de6b7c36c (patch)
treec75bec8d6f432b287816338db179d67fc859ffdf
parentecd48ae244dbb6490989752fba99b58d84babfa6 (diff)
downloadsssd-8b2bd0587af6ed6bbd7eab7a332ec88de6b7c36c.zip
sssd-8b2bd0587af6ed6bbd7eab7a332ec88de6b7c36c.tar.gz
sssd-8b2bd0587af6ed6bbd7eab7a332ec88de6b7c36c.tar.xz
cert_to_ssh_key: properly add leading 0 to bignums
In the ssh keys a leading 0 is added to the bignums of the RSA modulus and exponent if the leading bit is set to avoid the interpretation as a negative number. Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-rw-r--r--src/util/cert/nss/cert.c32
1 files changed, 24 insertions, 8 deletions
diff --git a/src/util/cert/nss/cert.c b/src/util/cert/nss/cert.c
index 7bf9a8b..b5e0ff9 100644
--- a/src/util/cert/nss/cert.c
+++ b/src/util/cert/nss/cert.c
@@ -239,6 +239,8 @@ errno_t cert_to_ssh_key(TALLOC_CTX *mem_ctx, const char *ca_db,
parameters.length = sizeof (parameters);
SECStatus rv;
SECStatus rv_verify;
+ size_t exponent_prefix_len;
+ size_t modulus_prefix_len;
if (der_blob == NULL || der_size == 0) {
return EINVAL;
@@ -341,10 +343,21 @@ errno_t cert_to_ssh_key(TALLOC_CTX *mem_ctx, const char *ca_db,
goto done;
}
+ /* Looks like nss drops the leading 00 which afaik is added to make sure
+ * the bigint is handled as positive number if the leading bit is set. */
+ exponent_prefix_len = 0;
+ if (cert_pub_key->u.rsa.publicExponent.data[0] & 0x80) {
+ exponent_prefix_len = 1;
+ }
+
+ modulus_prefix_len = 0;
+ if (cert_pub_key->u.rsa.modulus.data[0] & 0x80) {
+ modulus_prefix_len = 1;
+ }
size = SSH_RSA_HEADER_LEN + 3 * sizeof(uint32_t)
+ cert_pub_key->u.rsa.modulus.len
+ cert_pub_key->u.rsa.publicExponent.len
- + 1; /* see comment about missing 00 below */
+ + exponent_prefix_len + modulus_prefix_len;
buf = talloc_size(mem_ctx, size);
if (buf == NULL) {
@@ -358,17 +371,20 @@ errno_t cert_to_ssh_key(TALLOC_CTX *mem_ctx, const char *ca_db,
SAFEALIGN_SET_UINT32(buf, htobe32(SSH_RSA_HEADER_LEN), &c);
safealign_memcpy(&buf[c], SSH_RSA_HEADER, SSH_RSA_HEADER_LEN, &c);
SAFEALIGN_SET_UINT32(&buf[c],
- htobe32(cert_pub_key->u.rsa.publicExponent.len), &c);
+ htobe32(cert_pub_key->u.rsa.publicExponent.len
+ + exponent_prefix_len), &c);
+ if (exponent_prefix_len == 1) {
+ SAFEALIGN_SETMEM_VALUE(&buf[c], '\0', unsigned char, &c);
+ }
safealign_memcpy(&buf[c], cert_pub_key->u.rsa.publicExponent.data,
cert_pub_key->u.rsa.publicExponent.len, &c);
- /* Looks like nss drops the leading 00 which afaik is added to make sure
- * the bigint is handled as positive number */
- /* TODO: make a better check if 00 must be added or not, e.g. ... & 0x80)
- */
SAFEALIGN_SET_UINT32(&buf[c],
- htobe32(cert_pub_key->u.rsa.modulus.len + 1 ), &c);
- SAFEALIGN_SETMEM_VALUE(&buf[c], '\0', unsigned char, &c);
+ htobe32(cert_pub_key->u.rsa.modulus.len
+ + modulus_prefix_len ), &c);
+ if (modulus_prefix_len == 1) {
+ SAFEALIGN_SETMEM_VALUE(&buf[c], '\0', unsigned char, &c);
+ }
safealign_memcpy(&buf[c], cert_pub_key->u.rsa.modulus.data,
cert_pub_key->u.rsa.modulus.len, &c);