summaryrefslogtreecommitdiff
path: root/sshbuf-misc.c
diff options
context:
space:
mode:
Diffstat (limited to 'sshbuf-misc.c')
-rw-r--r--sshbuf-misc.c96
1 files changed, 83 insertions, 13 deletions
diff --git a/sshbuf-misc.c b/sshbuf-misc.c
index 15dcfbc79..a73f008b0 100644
--- a/sshbuf-misc.c
+++ b/sshbuf-misc.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshbuf-misc.c,v 1.6 2016/05/02 08:49:03 djm Exp $ */ 1/* $OpenBSD: sshbuf-misc.c,v 1.11 2019/07/30 05:04:49 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2011 Damien Miller 3 * Copyright (c) 2011 Damien Miller
4 * 4 *
@@ -23,7 +23,7 @@
23#include <errno.h> 23#include <errno.h>
24#include <stdlib.h> 24#include <stdlib.h>
25#ifdef HAVE_STDINT_H 25#ifdef HAVE_STDINT_H
26#include <stdint.h> 26# include <stdint.h>
27#endif 27#endif
28#include <stdio.h> 28#include <stdio.h>
29#include <limits.h> 29#include <limits.h>
@@ -89,24 +89,58 @@ sshbuf_dtob16(struct sshbuf *buf)
89 return ret; 89 return ret;
90} 90}
91 91
92int
93sshbuf_dtob64(const struct sshbuf *d, struct sshbuf *b64, int wrap)
94{
95 size_t i, slen = 0;
96 char *s = NULL;
97 int r;
98
99 if (d == NULL || b64 == NULL || sshbuf_len(d) >= SIZE_MAX / 2)
100 return SSH_ERR_INVALID_ARGUMENT;
101 if (sshbuf_len(d) == 0)
102 return 0;
103 slen = ((sshbuf_len(d) + 2) / 3) * 4 + 1;
104 if ((s = malloc(slen)) == NULL)
105 return SSH_ERR_ALLOC_FAIL;
106 if (b64_ntop(sshbuf_ptr(d), sshbuf_len(d), s, slen) == -1) {
107 r = SSH_ERR_INTERNAL_ERROR;
108 goto fail;
109 }
110 if (wrap) {
111 for (i = 0; s[i] != '\0'; i++) {
112 if ((r = sshbuf_put_u8(b64, s[i])) != 0)
113 goto fail;
114 if (i % 70 == 69 && (r = sshbuf_put_u8(b64, '\n')) != 0)
115 goto fail;
116 }
117 if ((i - 1) % 70 != 69 && (r = sshbuf_put_u8(b64, '\n')) != 0)
118 goto fail;
119 } else {
120 if ((r = sshbuf_put(b64, s, strlen(s))) != 0)
121 goto fail;
122 }
123 /* Success */
124 r = 0;
125 fail:
126 freezero(s, slen);
127 return r;
128}
129
92char * 130char *
93sshbuf_dtob64(struct sshbuf *buf) 131sshbuf_dtob64_string(const struct sshbuf *buf, int wrap)
94{ 132{
95 size_t len = sshbuf_len(buf), plen; 133 struct sshbuf *tmp;
96 const u_char *p = sshbuf_ptr(buf);
97 char *ret; 134 char *ret;
98 int r;
99 135
100 if (len == 0) 136 if ((tmp = sshbuf_new()) == NULL)
101 return strdup("");
102 plen = ((len + 2) / 3) * 4 + 1;
103 if (SIZE_MAX / 2 <= len || (ret = malloc(plen)) == NULL)
104 return NULL; 137 return NULL;
105 if ((r = b64_ntop(p, len, ret, plen)) == -1) { 138 if (sshbuf_dtob64(buf, tmp, wrap) != 0) {
106 explicit_bzero(ret, plen); 139 sshbuf_free(tmp);
107 free(ret);
108 return NULL; 140 return NULL;
109 } 141 }
142 ret = sshbuf_dup_string(tmp);
143 sshbuf_free(tmp);
110 return ret; 144 return ret;
111} 145}
112 146
@@ -159,3 +193,39 @@ sshbuf_dup_string(struct sshbuf *buf)
159 return r; 193 return r;
160} 194}
161 195
196int
197sshbuf_cmp(const struct sshbuf *b, size_t offset,
198 const void *s, size_t len)
199{
200 if (sshbuf_ptr(b) == NULL)
201 return SSH_ERR_INTERNAL_ERROR;
202 if (offset > SSHBUF_SIZE_MAX || len > SSHBUF_SIZE_MAX || len == 0)
203 return SSH_ERR_INVALID_ARGUMENT;
204 if (offset + len > sshbuf_len(b))
205 return SSH_ERR_MESSAGE_INCOMPLETE;
206 if (timingsafe_bcmp(sshbuf_ptr(b) + offset, s, len) != 0)
207 return SSH_ERR_INVALID_FORMAT;
208 return 0;
209}
210
211int
212sshbuf_find(const struct sshbuf *b, size_t start_offset,
213 const void *s, size_t len, size_t *offsetp)
214{
215 void *p;
216
217 if (offsetp != NULL)
218 *offsetp = 0;
219 if (sshbuf_ptr(b) == NULL)
220 return SSH_ERR_INTERNAL_ERROR;
221 if (start_offset > SSHBUF_SIZE_MAX || len > SSHBUF_SIZE_MAX || len == 0)
222 return SSH_ERR_INVALID_ARGUMENT;
223 if (start_offset > sshbuf_len(b) || start_offset + len > sshbuf_len(b))
224 return SSH_ERR_MESSAGE_INCOMPLETE;
225 if ((p = memmem(sshbuf_ptr(b) + start_offset,
226 sshbuf_len(b) - start_offset, s, len)) == NULL)
227 return SSH_ERR_INVALID_FORMAT;
228 if (offsetp != NULL)
229 *offsetp = (const u_char *)p - sshbuf_ptr(b);
230 return 0;
231}