summaryrefslogtreecommitdiff
path: root/libs/libssh2/src/pem.c
diff options
context:
space:
mode:
Diffstat (limited to 'libs/libssh2/src/pem.c')
-rw-r--r--libs/libssh2/src/pem.c324
1 files changed, 324 insertions, 0 deletions
diff --git a/libs/libssh2/src/pem.c b/libs/libssh2/src/pem.c
new file mode 100644
index 0000000000..9f51bba3b5
--- /dev/null
+++ b/libs/libssh2/src/pem.c
@@ -0,0 +1,324 @@
+/* Copyright (C) 2007 The Written Word, Inc.
+ * Copyright (C) 2008, Simon Josefsson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * Neither the name of the copyright holder nor the names
+ * of any other contributors may be used to endorse or
+ * promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ */
+
+#include "libssh2_priv.h"
+
+static int
+readline(char *line, int line_size, FILE * fp)
+{
+ size_t len;
+
+ if (!line) {
+ return -1;
+ }
+ if (!fgets(line, line_size, fp)) {
+ return -1;
+ }
+
+ if (*line) {
+ len = strlen(line);
+ if (len > 0 && line[len - 1] == '\n') {
+ line[len - 1] = '\0';
+ }
+ }
+
+ if (*line) {
+ len = strlen(line);
+ if (len > 0 && line[len - 1] == '\r') {
+ line[len - 1] = '\0';
+ }
+ }
+
+ return 0;
+}
+
+static int
+readline_memory(char *line, size_t line_size,
+ const char *filedata, size_t filedata_len,
+ size_t *filedata_offset)
+{
+ size_t off, len;
+
+ off = *filedata_offset;
+
+ for (len = 0; off + len < filedata_len && len < line_size; len++) {
+ if (filedata[off + len] == '\n' ||
+ filedata[off + len] == '\r') {
+ break;
+ }
+ }
+
+ if (len) {
+ memcpy(line, filedata + off, len);
+ *filedata_offset += len;
+ }
+
+ line[len] = '\0';
+ *filedata_offset += 1;
+
+ return 0;
+}
+
+#define LINE_SIZE 128
+
+int
+_libssh2_pem_parse(LIBSSH2_SESSION * session,
+ const char *headerbegin,
+ const char *headerend,
+ FILE * fp, unsigned char **data, unsigned int *datalen)
+{
+ char line[LINE_SIZE];
+ char *b64data = NULL;
+ unsigned int b64datalen = 0;
+ int ret;
+
+ do {
+ *line = '\0';
+
+ if (readline(line, LINE_SIZE, fp)) {
+ return -1;
+ }
+ }
+ while (strcmp(line, headerbegin) != 0);
+
+ *line = '\0';
+
+ do {
+ if (*line) {
+ char *tmp;
+ size_t linelen;
+
+ linelen = strlen(line);
+ tmp = LIBSSH2_REALLOC(session, b64data, b64datalen + linelen);
+ if (!tmp) {
+ ret = -1;
+ goto out;
+ }
+ memcpy(tmp + b64datalen, line, linelen);
+ b64data = tmp;
+ b64datalen += linelen;
+ }
+
+ *line = '\0';
+
+ if (readline(line, LINE_SIZE, fp)) {
+ ret = -1;
+ goto out;
+ }
+ } while (strcmp(line, headerend) != 0);
+
+ if (!b64data) {
+ return -1;
+ }
+
+ if (libssh2_base64_decode(session, (char**) data, datalen,
+ b64data, b64datalen)) {
+ ret = -1;
+ goto out;
+ }
+
+ ret = 0;
+ out:
+ if (b64data) {
+ LIBSSH2_FREE(session, b64data);
+ }
+ return ret;
+}
+
+int
+_libssh2_pem_parse_memory(LIBSSH2_SESSION * session,
+ const char *headerbegin,
+ const char *headerend,
+ const char *filedata, size_t filedata_len,
+ unsigned char **data, unsigned int *datalen)
+{
+ char line[LINE_SIZE];
+ char *b64data = NULL;
+ unsigned int b64datalen = 0;
+ size_t off = 0;
+ int ret;
+
+ do {
+ *line = '\0';
+
+ if (readline_memory(line, LINE_SIZE, filedata, filedata_len, &off)) {
+ return -1;
+ }
+ }
+ while (strcmp(line, headerbegin) != 0);
+
+ *line = '\0';
+
+ do {
+ if (*line) {
+ char *tmp;
+ size_t linelen;
+
+ linelen = strlen(line);
+ tmp = LIBSSH2_REALLOC(session, b64data, b64datalen + linelen);
+ if (!tmp) {
+ ret = -1;
+ goto out;
+ }
+ memcpy(tmp + b64datalen, line, linelen);
+ b64data = tmp;
+ b64datalen += linelen;
+ }
+
+ *line = '\0';
+
+ if (readline_memory(line, LINE_SIZE, filedata, filedata_len, &off)) {
+ ret = -1;
+ goto out;
+ }
+ } while (strcmp(line, headerend) != 0);
+
+ if (!b64data) {
+ return -1;
+ }
+
+ if (libssh2_base64_decode(session, (char**) data, datalen,
+ b64data, b64datalen)) {
+ ret = -1;
+ goto out;
+ }
+
+ ret = 0;
+ out:
+ if (b64data) {
+ LIBSSH2_FREE(session, b64data);
+ }
+ return ret;
+}
+
+static int
+read_asn1_length(const unsigned char *data,
+ unsigned int datalen, unsigned int *len)
+{
+ unsigned int lenlen;
+ int nextpos;
+
+ if (datalen < 1) {
+ return -1;
+ }
+ *len = data[0];
+
+ if (*len >= 0x80) {
+ lenlen = *len & 0x7F;
+ *len = data[1];
+ if (1 + lenlen > datalen) {
+ return -1;
+ }
+ if (lenlen > 1) {
+ *len <<= 8;
+ *len |= data[2];
+ }
+ } else {
+ lenlen = 0;
+ }
+
+ nextpos = 1 + lenlen;
+ if (lenlen > 2 || 1 + lenlen + *len > datalen) {
+ return -1;
+ }
+
+ return nextpos;
+}
+
+int
+_libssh2_pem_decode_sequence(unsigned char **data, unsigned int *datalen)
+{
+ unsigned int len;
+ int lenlen;
+
+ if (*datalen < 1) {
+ return -1;
+ }
+
+ if ((*data)[0] != '\x30') {
+ return -1;
+ }
+
+ (*data)++;
+ (*datalen)--;
+
+ lenlen = read_asn1_length(*data, *datalen, &len);
+ if (lenlen < 0 || lenlen + len != *datalen) {
+ return -1;
+ }
+
+ *data += lenlen;
+ *datalen -= lenlen;
+
+ return 0;
+}
+
+int
+_libssh2_pem_decode_integer(unsigned char **data, unsigned int *datalen,
+ unsigned char **i, unsigned int *ilen)
+{
+ unsigned int len;
+ int lenlen;
+
+ if (*datalen < 1) {
+ return -1;
+ }
+
+ if ((*data)[0] != '\x02') {
+ return -1;
+ }
+
+ (*data)++;
+ (*datalen)--;
+
+ lenlen = read_asn1_length(*data, *datalen, &len);
+ if (lenlen < 0 || lenlen + len > *datalen) {
+ return -1;
+ }
+
+ *data += lenlen;
+ *datalen -= lenlen;
+
+ *i = *data;
+ *ilen = len;
+
+ *data += len;
+ *datalen -= len;
+
+ return 0;
+}