summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGordon GECOS <u@adam>2023-11-24 23:01:55 -0500
committerGordon GECOS <u@adam>2023-11-25 11:12:26 -0500
commit53927610e50170cc0d7ead7b17e6c933f88f9568 (patch)
tree434b1c6a1036a980738c6c2675a8d780976911c2
parentca48d24bf83a7ce68f3f93449012da40b61015e5 (diff)
base64
-rw-r--r--src/base64.pk216
-rwxr-xr-xsrc/ssh-keysign.pk69
2 files changed, 247 insertions, 38 deletions
diff --git a/src/base64.pk b/src/base64.pk
new file mode 100644
index 0000000..b35718d
--- /dev/null
+++ b/src/base64.pk
@@ -0,0 +1,216 @@
1/* base64.pk - base64 ASCII encoding for GNU poke. */
2
3/* This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17/* Copyright (C) 2023 Jose E. Marchesi.
18 *
19 * Poke version of the Internet Software Consortium C implementation
20 * of base64, which is:
21 *
22 * Copyright (c) 1996-1999 by Internet Software Consortium.
23 *
24 * Permission to use, copy, modify, and distribute this software for any
25 * purpose with or without fee is hereby granted, provided that the above
26 * copyright notice and this permission notice appear in all copies.
27 *
28 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
29 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
30 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
31 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
32 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
33 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
34 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
35 * SOFTWARE. */
36
37/* The base64 encoding is specified by
38 https://datatracker.ietf.org/doc/html/rfc4648 */
39
40var base64_chars
41 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
42
43fun base64_encode = (uint<8>[] src) string:
44{
45 var srclength = src'length;
46 var targsize = (src'length /^ 3) * 4;
47 var target = uint<8>[targsize]();
48 var input = uint<8>[3]();
49 var output = uint<8>[4]();
50 var s = 0UL;
51 var datalength = 0UL;
52
53 while (srclength > 2)
54 {
55 input[0] = src[s++];
56 input[1] = src[s++];
57 input[2] = src[s++];
58 srclength -= 3;
59
60 output[0] = input[0] .>> 2;
61 output[1] = ((input[0] & 0x03) <<. 4) + (input[1] .>> 4);
62 output[2] = ((input[1] & 0x0f) <<. 2) + (input[2] .>> 6);
63 output[3] = input[2] & 0x3f;
64 assert (output[0] < 64);
65 assert (output[1] < 64);
66 assert (output[2] < 64);
67 assert (output[3] < 64);
68
69 target[datalength++] = base64_chars[output[0]];
70 target[datalength++] = base64_chars[output[1]];
71 target[datalength++] = base64_chars[output[2]];
72 target[datalength++] = base64_chars[output[3]];
73 }
74
75 /* Do now the padding. */
76 if (srclength != 0)
77 {
78 input[2] = '\0';
79 input[1] = '\0';
80 input[0] = '\0';
81
82 for (var i = 0; i < srclength; i++)
83 input[i] = src[s++];
84
85 output[0] = input[0] .>> 2;
86 output[1] = ((input[0] & 0x03) <<. 4) + (input[1] .>> 4);
87 output[2] = ((input[1] & 0x0f) <<. 2) + (input[2] .>> 6);
88 assert (output[0] < 64);
89 assert (output[1] < 64);
90 assert (output[2] < 64);
91
92 target[datalength++] = base64_chars[output[0]];
93 target[datalength++] = base64_chars[output[1]];
94 if (srclength == 1)
95 target[datalength++] = '=';
96 else
97 target[datalength++] = base64_chars[output[2]];
98 target[datalength++] = '=';
99 }
100
101 return catos (target);
102}
103
104fun base64_decode = (string src) uint<8>[]:
105{
106 fun invalid_input = (string cause, int<32> position) void:
107 {
108 raise Exception { code = EC_inval,
109 name = "invalid argument",
110 msg = cause + format (" at position %i32d", position) };
111 }
112
113 var srclength = src'length;
114 var targsize = (rtrim (src, "=")'length /^ 4) * 3;
115 var target = uint<8>[targsize+1]();
116
117 var state = 0;
118 var tarindex = 0;
119 var ch = 0UB;
120 var s = 0UL;
121
122 while (s < srclength)
123 {
124 ch = src[s++];
125
126 if (ch == ' ')
127 continue;
128
129 if (ch == '=')
130 {
131 s--;
132 break;
133 }
134
135 var pos = strchr (base64_chars, ch);
136
137 if (pos == base64_chars'length) /* A non-base64 character. */
138 invalid_input ("non-base64 character passed to base_64_decode", s - 1);
139
140 if (state == 0)
141 {
142 assert (tarindex < targsize);
143 target[tarindex] = pos <<. 2;
144 state = 1;
145 }
146 else if (state == 1)
147 {
148 assert (tarindex + 1 < targsize);
149 target[tarindex] |= pos .>> 4;
150 target[tarindex + 1] = (pos & 0x0f) <<. 4;
151 tarindex += 1;
152 state = 2;
153 }
154 else if (state == 2)
155 {
156 assert (tarindex + 1 < targsize);
157 target[tarindex] |= pos .>> 2;
158 target[tarindex + 1] = (pos & 0x03) <<. 6;
159 tarindex += 1;
160 state = 3;
161 }
162 else if (state == 3)
163 {
164 assert (tarindex < targsize);
165 target[tarindex] |= pos;
166 tarindex++;
167 state = 0;
168 }
169 else
170 /* Unreachable. */
171 assert (0);
172 }
173
174 /* We are done with the base-64 chars. Let's see if we ended on a
175 byte boundary, and/or with erroneous trailing characters. */
176 if (ch == '=')
177 {
178 ch = src[s++];
179 if (state == 0 || state == 1)
180 {
181 invalid_input ("invalid `=' in string passed to base64_decode",
182 s - 1);
183 }
184 else if (state == 2 || state == 3)
185 {
186 if (state == 2)
187 {
188 /* Skip any number of spaces. */
189 while (s < srclength)
190 {
191 ch = src[s++];
192 if (ch != ' ')
193 break;
194 }
195 /* Make sure there is another trailing = sign. */
196 if (ch != '=')
197 invalid_input ("expected `=' in string passed to base64_decode",
198 s - 1);
199 }
200
201 /* State 2 and 3. */
202 while (s < srclength)
203 {
204 ch = src[s++];
205 if (ch != ' ')
206 invalid_input ("expected whitespace in string passed to base64_decode",
207 s - 1);
208 }
209
210 if (target[tarindex] != 0)
211 raise E_inval;
212 }
213 }
214
215 return target[:tarindex];
216}
diff --git a/src/ssh-keysign.pk b/src/ssh-keysign.pk
index 1c17110..40ccd97 100755
--- a/src/ssh-keysign.pk
+++ b/src/ssh-keysign.pk
@@ -1,70 +1,64 @@
1#!/usr/bin/poke -L 1#!/usr/bin/poke -L
2!# 2!#
3 3
4load "src/base64.pk";
5
6fun encode = (any v) string:
7{
8 return base64_encode (uint<8>[v'size] @ v'ios : v'offset);
9}
10
4type SSH_String = 11type SSH_String =
5struct 12struct
6{ 13{
7 uint<32> size; 14 uint<32> size;
8 byte[size] data; 15 byte[size] bytes;
9}; 16};
10 17
11type SSH_Publickey = 18type SSH_Publickey_Blob =
12struct 19struct
13{ 20{
14 SSH_String key_type : catos(key_type.data) == "ssh-ed25519"; 21 SSH_String key_type : catos (key_type.bytes) == "ssh-ed25519";
15 SSH_String key_data : key_data.size == 32; 22 SSH_String key_data : key_data.size == 32;
16}; 23};
17 24
18type SSH_Signature = 25type SSH_Signature_Blob =
19struct 26struct
20{ 27{
21 SSH_String sig_type : catos(sig_type.data) == "ssh-ed25519"; 28 SSH_String sig_type : catos (sig_type.bytes) == "ssh-ed25519";
22 SSH_String sig_data; 29 SSH_String sig_data : sig_data.size == 64;
23}; 30};
24 31
25type SSH_Signature_String = 32type SSH_Signature_String =
26struct 33struct
27{ 34{
28 uint<32> size; 35 uint<32> size;
29 union { 36 SSH_Signature_Blob blob;
30 SSH_Signature sig;
31 byte[size] raw;
32 } data;
33}; 37};
34 38
35type SSH_Publickey_String = 39type SSH_Publickey_String =
36struct 40struct
37{ 41{
38 uint<32> size; 42 uint<32> size;
39 union { 43 SSH_Publickey_Blob blob;
40 SSH_Publickey key;
41 byte[size] raw;
42 } data;
43}; 44};
44 45
45type SSH_Signature = 46type SSH_Signature =
46struct 47struct
47{ 48{
48 uint<32> size; 49 byte[6] MAGIC_PREAMBLE : catos (MAGIC_PREAMBLE) == "SSHSIG";
49 byte[size] data;
50};
51
52type SSH_Signature_Blob =
53struct
54{
55 byte[6] MAGIC_PREAMBLE : catos(MAGIC_PREAMBLE) == "SSHSIG";
56 uint<32> SIG_VERSION : SIG_VERSION == 1; 50 uint<32> SIG_VERSION : SIG_VERSION == 1;
57 SSH_Publickey_String publickey; 51 SSH_Publickey_String publickey;
58 SSH_String namespace; 52 SSH_String namespace;
59 SSH_String reserved; 53 SSH_String reserved;
60 SSH_String hash_algorithm; 54 SSH_String hash_algorithm : catos (hash_algorithm.bytes) == "sha512";
61 SSH_Signature_String signature; 55 SSH_Signature_String signature;
62}; 56};
63 57
64if (!(argv'length in [1])) 58if (!(argv'length in [1]))
65 { 59 {
66 print("Usage: ssh-keysign.pk FILE\n"); 60 print ("Usage: ssh-keysign.pk FILE\n");
67 exit(1); 61 exit (1);
68 } 62 }
69 63
70var file_name = argv[0]; 64var file_name = argv[0];
@@ -72,19 +66,18 @@ var file_name = argv[0];
72try 66try
73 { 67 {
74 var fd = open (file_name, IOS_M_RDONLY); 68 var fd = open (file_name, IOS_M_RDONLY);
75 var sig = SSH_Signature_Blob @ fd : 0#B; 69 var sig = SSH_Signature @ fd : 0#B;
76 printf("%s: %s (%i32d bytes)\n", "publickey", 70 printf ("%s: %s %s (raw: %s)\n", "publickey",
77 catos(sig.publickey.data.key.key_type.data), 71 catos (sig.publickey.blob.key_type.bytes),
78 sig.publickey.data.key.key_data.size); 72 encode (sig.publickey.blob),
79 printf("%s: %s\n", "namespace", 73 encode (sig.publickey.blob.key_data.bytes));
80 catos(sig.namespace.data)); 74 printf ("%s: %v\n", "namespace", catos (sig.namespace.bytes));
81 printf("%s: <%i32d bytes>\n", "reserved", 75 printf ("%s: <%i32d bytes>\n", "reserved", sig.reserved.size);
82 sig.reserved.size); 76 printf ("%s: %s\n", "hash_algorithm", catos (sig.hash_algorithm.bytes));
83 printf("%s: %s\n", "hash_algorithm", 77 printf ("%s: %s %s (raw: %s)\n", "signature",
84 catos(sig.hash_algorithm.data)); 78 catos (sig.signature.blob.sig_type.bytes),
85 printf("%s: %s (%i32d bytes)\n", "signature", 79 encode (sig.signature.blob),
86 catos(sig.signature.data.sig.sig_type.data), 80 encode (sig.signature.blob.sig_data.bytes));
87 sig.signature.data.sig.sig_data.size);
88 close (fd); 81 close (fd);
89 } 82 }
90catch (Exception e) 83catch (Exception e)