aboutsummaryrefslogtreecommitdiff
path: root/src/pki_gcrypt.c
diff options
context:
space:
mode:
authorJustus Winter <justus@g10code.com>2016-03-30 11:53:24 +0200
committerAndreas Schneider <asn@cryptomilk.org>2016-05-02 12:07:07 +0200
commit3c69092cded3a12b4d589bd39302a1aaa36179d6 (patch)
tree108f12c66fb82cf41f0a222fd885636326c08b5b /src/pki_gcrypt.c
parente8b28f978e249a3bb50fa60f28f5796a792be644 (diff)
downloadlibssh-3c69092cded3a12b4d589bd39302a1aaa36179d6.tar.gz
libssh-3c69092cded3a12b4d589bd39302a1aaa36179d6.tar.xz
libssh-3c69092cded3a12b4d589bd39302a1aaa36179d6.zip
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@g10code.com> Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
Diffstat (limited to 'src/pki_gcrypt.c')
-rw-r--r--src/pki_gcrypt.c59
1 files changed, 59 insertions, 0 deletions
diff --git a/src/pki_gcrypt.c b/src/pki_gcrypt.c
index 4865ea35..982e3f46 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@cryptomilk.org>
+ * 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,63 @@ 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;
+ uint32_t len;
+
+ len = ssh_buffer_get_data(buffer, &type, 1);
+ if (len == 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;
+ }
+
+ len = ssh_buffer_get_data(buffer, &unused, 1);
+ if (len == 0) {
+ ssh_string_free(str);
+ return NULL;
+ }
+
+ if (unused == 0) {
+ len = ssh_buffer_get_data(buffer, ssh_string_data(str), size);
+ if (len == 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;
+
+ len = ssh_buffer_get_data(buffer, &c, 1);
+ if (len == 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;