Check-in [eb360ae2a4]
Overview
Comment:Added start of additional internal functions
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: eb360ae2a459140a997f0adb921aa4de6d8ced3079dfd4f8d620f16542cd4a4a
User & Date: rkeene on 2018-07-01 20:48:26
Other Links: manifest | tags
Context
2018-07-01
20:55
Ensure we include the headers for memcpy() check-in: f12cd8142a user: rkeene tags: trunk
20:48
Added start of additional internal functions check-in: eb360ae2a4 user: rkeene tags: trunk
20:06
Added patch to allow deriving the public key component from a secret key check-in: f08c39c4fe user: rkeene tags: trunk
Changes

Modified Makefile.in from [7a0a4eadd8] to [5c42621220].

21
22
23
24
25
26
27



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

45







+
+
+














-
+

tweetnacl/tweetnacl.o:
	$(MAKE) -C tweetnacl tweetnacl.o

blake2b/blake2b.o:
	$(MAKE) -C blake2b blake2b.o

test: @EXTENSION_TARGET@
	cd build/test && ./test.tcl

clean:
	rm -f @EXTENSION_TARGET@ nano.o
	$(MAKE) -C tweetnacl clean
	$(MAKE) -C blake2b clean

distclean:
	rm -f @EXTENSION_TARGET@ nano.o
	rm -f Makefile pkgIndex.tcl config.log config.status
	$(MAKE) -C tweetnacl distclean
	$(MAKE) -C blake2b distclean

mrproper: distclean
	rm -f configure aclocal.m4 config.guess config.sub install-sh

.PHONY: all clean distclean mrproper
.PHONY: all test clean distclean mrproper

Modified build/test/test.tcl from [9220486097] to [9536bccf33].

1
2
3
4
5
6

7
8
9













10
11




1
2
3
4
5
6
7



8
9
10
11
12
13
14
15
16
17
18
19
20
21

22
23
24
25






+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+
+
+
+
#! /usr/bin/env tclsh

lappend auto_path [file join [file dirname [info script]] .. ..]

package require nano

proc test1 {} {
set key [binary decode hex 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000]
puts "Key Length: [string length $key]"
set signed [binary encode hex [::nano::internal::sign "" $key]]
	set data [binary decode hex 0000000000000000000000000000000000000000000000000000000000000000]
	set key  [binary decode hex C4D214F19E706E9C7487CEF00DE8059200C32414F0ED82E5E33B523AEDF719BA]
	set signed [string toupper [binary encode hex [::nano::internal::signDetached $data $key]]]
	set signed_expected 1C2DE9B8A71215F949A11BBEA7EFA4ECD67A8C2B5A9AD98AE6B1AB7F7A3D2CFD715F570309148C7B39C346FB9B91B321D7E75BD598F271AF31AB60A99D086709

	if {$signed ne $signed_expected} {
		puts "\[FAIL\] Got: $signed"
		puts "\[FAIL\] Exp: $signed_expected"
		return false
	}

	set pubKey [::nano::internal::publicKey $key]
	set pubKey [binary encode hex $pubKey]

puts $signed
	puts "Pub: $pubKey"
}

test1

Modified nano.c from [a802819e09] to [d6f90a57ca].

56
57
58
59
60
61
62



































































63

64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88







89
90
91


92
93
94
95
96
97
98



99
100
101
102
103
104






























































105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123



124
125
126
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129

130
131
132
133
134
135
136
137
138
139
140
141
142







143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175

176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255

256
257
258
259
260
261







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+












-
-
-
-
-
-
-






+
+
+
+
+
+
+



+
+







+
+
+





-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


















-
+
+
+



		buffer[length - 1] = (length % 256);
		length--;
	}

	return;
}

#define NANO_SECRET_KEY_LENGTH (crypto_sign_SECRETKEYBYTES - crypto_sign_PUBLICKEYBYTES)
#define NANO_PUBLIC_KEY_LENGTH (crypto_sign_PUBLICKEYBYTES)

static unsigned char *nano_parse_secret_key(Tcl_Obj *secret_key_only_obj, int *out_key_length) {
	unsigned char *secret_key, *public_key, *secret_key_only;
	int secret_key_length, secret_key_only_length;

	secret_key_only = Tcl_GetByteArrayFromObj(secret_key_only_obj, &secret_key_only_length);
	if (secret_key_only_length != NANO_SECRET_KEY_LENGTH) {
		return(NULL);
	}

	if ((NANO_SECRET_KEY_LENGTH + NANO_PUBLIC_KEY_LENGTH) != crypto_sign_SECRETKEYBYTES) {
		return(NULL);
	}

	secret_key_length = crypto_sign_SECRETKEYBYTES;
	secret_key = (unsigned char *) Tcl_AttemptAlloc(secret_key_length);
	if (!secret_key) {
		return(NULL);
	}

	memcpy(secret_key, secret_key_only, secret_key_only_length);
	public_key = secret_key + secret_key_only_length;
	crypto_sign_keypair(public_key, secret_key, 0);

	*out_key_length = secret_key_length;
	return(secret_key);
}

static int nano_tcl_secret_key_to_public_key(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) {
	unsigned char *secret_key, *public_key;
	int secret_key_length, public_key_length;

	if (objc != 2) {
		Tcl_WrongNumArgs(interp, 1, objv, "secretKey");

		return(TCL_ERROR);
	}

	secret_key = Tcl_GetByteArrayFromObj(objv[1], &secret_key_length);
	if (secret_key_length != NANO_SECRET_KEY_LENGTH) {
		Tcl_SetResult(interp, "Secret key is not the right size", NULL);

		return(TCL_ERROR);
	}

	public_key_length = NANO_PUBLIC_KEY_LENGTH;
	public_key = (unsigned char *) Tcl_AttemptAlloc(public_key_length);
	if (!public_key) {
		Tcl_SetResult(interp, "Internal error", NULL);

		return(TCL_ERROR);
	}

	crypto_sign_keypair(public_key, secret_key, 0);

	Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(public_key, public_key_length));

	Tcl_Free((char *) public_key);

	return(TCL_OK);

	/* NOTREACH */
	clientData = clientData;
}

static int nano_sign(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) {
static int nano_tcl_sign_detached(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) {
	int cs_ret;
	unsigned char *signature, *data, *secret_key;
	unsigned long long signature_length;
	int data_length, secret_key_length;

	if (objc != 3) {
		Tcl_WrongNumArgs(interp, 1, objv, "data secretKey");

		return(TCL_ERROR);
	}

	data = Tcl_GetByteArrayFromObj(objv[1], &data_length);
	secret_key = Tcl_GetByteArrayFromObj(objv[2], &secret_key_length);
	if (secret_key_length != crypto_sign_SECRETKEYBYTES) {
		Tcl_SetResult(interp, "Secret key is not the right size", NULL);

		return(TCL_ERROR);
	}

	signature_length = data_length + crypto_sign_BYTES;
	if (signature_length >= UINT_MAX) {
		Tcl_SetResult(interp, "Input message too long", NULL);

		return(TCL_ERROR);
	}

	secret_key = nano_parse_secret_key(objv[2], &secret_key_length);
	if (secret_key == NULL) {
		Tcl_SetResult(interp, "Secret key is not the right size", NULL);

		return(TCL_ERROR);
	}

	signature = (unsigned char *) Tcl_AttemptAlloc(signature_length);
	if (!signature) {
		Tcl_Free((char *) secret_key);

		Tcl_SetResult(interp, "Unable to allocate memory", NULL);

		return(TCL_ERROR);
	}

	cs_ret = crypto_sign(signature, &signature_length, data, data_length, secret_key);
	if (cs_ret != 0) {
		Tcl_Free((char *) secret_key);
		Tcl_Free((char *) signature);

		Tcl_SetResult(interp, "crypto_sign failed", NULL);

		return(TCL_ERROR);
	}

	Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(signature, signature_length));
	Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(signature, crypto_sign_BYTES));

	Tcl_Free((char *) signature);
	Tcl_Free((char *) secret_key);

	return(TCL_OK);

	/* NOTREACH */
	clientData = clientData;
}

static int nano_tcl_verify_detached(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) {
	int cso_ret;
	unsigned char *signature, *data, *signed_data, *public_key;
	int signature_length, data_length, signed_data_length, public_key_length;
	unsigned long long data_length_nacl;

	if (objc != 4) {
		Tcl_WrongNumArgs(interp, 1, objv, "data signature publicKey");

		return(TCL_ERROR);
	}

	data = Tcl_GetByteArrayFromObj(objv[1], &data_length);
	signature = Tcl_GetByteArrayFromObj(objv[2], &signature_length);
	if (signature_length != crypto_sign_BYTES) {
		Tcl_SetResult(interp, "Signature is not the right size", NULL);

		return(TCL_ERROR);
	}

	public_key = Tcl_GetByteArrayFromObj(objv[3], &public_key_length);
	if (public_key_length != NANO_PUBLIC_KEY_LENGTH) {
		Tcl_SetResult(interp, "Public key is not the right size", NULL);

		return(TCL_ERROR);
	}

	signed_data_length = data_length + signature_length;
	signed_data = (unsigned char *) Tcl_AttemptAlloc(signed_data_length);
	if (!signed_data) {
		Tcl_SetResult(interp, "Internal error", NULL);

		return(TCL_ERROR);
	}

	memcpy(signed_data, signature, signature_length);
	memcpy(signed_data + signature_length, data, data_length);

	data_length_nacl = data_length;
	cso_ret = crypto_sign_open(data, &data_length_nacl, signed_data, signed_data_length, public_key);
	if (cso_ret != 0) {
		Tcl_Free((char *) signed_data);

		Tcl_SetResult(interp, "crypto_sign_open failed", NULL);

		return(TCL_ERROR);
	}

	Tcl_Free((char *) signed_data);

	/* XXX:TODO: Validate */

	return(TCL_OK);

	/* NOTREACH */
	clientData = clientData;
}

int Nano_Init(Tcl_Interp *interp) {
#ifdef USE_TCL_STUBS
	const char *tclInitStubs_ret;

	/* Initialize Stubs */
	tclInitStubs_ret = Tcl_InitStubs(interp, TCL_PATCH_LEVEL, 0);
	if (!tclInitStubs_ret) {
		return(TCL_ERROR);
	}
#endif

	Tcl_CreateObjCommand(interp, "::nano::internal::sign", nano_sign, NULL, NULL);
	Tcl_CreateObjCommand(interp, "::nano::internal::signDetached", nano_tcl_sign_detached, NULL, NULL);
	Tcl_CreateObjCommand(interp, "::nano::internal::publicKey", nano_tcl_secret_key_to_public_key, NULL, NULL);
	Tcl_CreateObjCommand(interp, "::nano::internal::verifyDetached", nano_tcl_verify_detached, NULL, NULL);

	return(TCL_OK);
}