[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 1/3] pki_gcrypt: Add primitive to read ASN.1 bit strings


* src/pki_gcrypt.c (ASN1_BIT_STRING): New macro.
(asn1_get_bit_string): New function.

Signed-off-by: Justus Winter <justus@xxxxxxxxxxx>
---
 src/pki_gcrypt.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)

diff --git a/src/pki_gcrypt.c b/src/pki_gcrypt.c
index 24d7d9b..0d847e9 100644
--- a/src/pki_gcrypt.c
+++ b/src/pki_gcrypt.c
@@ -5,6 +5,7 @@
  *
  * Copyright (c) 2003-2009 Aris Adamantiadis
  * Copyright (c) 2009-2011 Andreas Schneider <asn@xxxxxxxxxxxxxx>
+ * Copyright (C) 2016 g10 Code GmbH
  *
  * The SSH Library is free software; you can redistribute it and/or modify
  * it under the terms of the GNU Lesser General Public License as published by
@@ -48,6 +49,7 @@
 #define MAX_KEY_SIZE 32
 #define MAX_PASSPHRASE_SIZE 1024
 #define ASN1_INTEGER 2
+#define ASN1_BIT_STRING 3
 #define ASN1_SEQUENCE 48
 #define PKCS5_SALT_LEN 8
 
@@ -142,6 +144,57 @@ static ssh_string asn1_get_int(ssh_buffer buffer) {
   return asn1_get(buffer, ASN1_INTEGER);
 }
 
+static ssh_string asn1_get_bit_string(ssh_buffer buffer) {
+    ssh_string str;
+    unsigned char type;
+    uint32_t size;
+    unsigned char unused, last, *p;
+
+    if (ssh_buffer_get_data(buffer, &type, 1) == 0
+        || type != ASN1_BIT_STRING) {
+        return NULL;
+    }
+    size = asn1_get_len(buffer);
+    if (size == 0) {
+        return NULL;
+    }
+
+    /* The first octet encodes the number of unused bits.  */
+    size -= 1;
+
+    str = ssh_string_new(size);
+    if (str == NULL) {
+        return NULL;
+    }
+
+    if (ssh_buffer_get_data(buffer, &unused, 1) == 0) {
+        ssh_string_free(str);
+        return NULL;
+    }
+
+    if (unused == 0) {
+        if (ssh_buffer_get_data(buffer, ssh_string_data(str), size) == 0) {
+            ssh_string_free(str);
+            return NULL;
+        }
+        return str;
+    }
+
+    /* The bit string is padded at the end, we must shift the whole
+       string by UNUSED bits.  */
+    for (p = ssh_string_data(str), last = 0; size; size--, p++) {
+        unsigned char c;
+        if (ssh_buffer_get_data(buffer, &c, 1) == 0) {
+            ssh_string_free(str);
+            return NULL;
+        }
+        *p = last | (c >> unused);
+        last = c << (8 - unused);
+    }
+
+    return str;
+}
+
 static int asn1_check_sequence(ssh_buffer buffer) {
   unsigned char *j = NULL;
   unsigned char tmp;
-- 
2.1.4


Follow-Ups:
[PATCH 2/3] pki_gcrypt: Handle ECDSA keys and signaturesJustus Winter <justus@xxxxxxxxxxx>
[PATCH 3/3] ecdh: Implement ECDH using libgcryptJustus Winter <justus@xxxxxxxxxxx>
Archive administrator: postmaster@lists.cynapses.org