xref: /inferno-os/appl/lib/crypt/pkcs.b (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsythimplement PKCS;
2*37da2899SCharles.Forsyth
3*37da2899SCharles.Forsythinclude "sys.m";
4*37da2899SCharles.Forsyth	sys				: Sys;
5*37da2899SCharles.Forsyth
6*37da2899SCharles.Forsythinclude "keyring.m";
7*37da2899SCharles.Forsyth	keyring				: Keyring;
8*37da2899SCharles.Forsyth	IPint				: import keyring;
9*37da2899SCharles.Forsyth	DESstate			: import keyring;
10*37da2899SCharles.Forsyth
11*37da2899SCharles.Forsythinclude "security.m";
12*37da2899SCharles.Forsyth	random				: Random;
13*37da2899SCharles.Forsyth
14*37da2899SCharles.Forsythinclude "asn1.m";
15*37da2899SCharles.Forsyth	asn1				: ASN1;
16*37da2899SCharles.Forsyth	Elem, Oid			: import asn1;
17*37da2899SCharles.Forsyth
18*37da2899SCharles.Forsythinclude "pkcs.m";
19*37da2899SCharles.Forsyth
20*37da2899SCharles.Forsyth# pkcs object identifiers
21*37da2899SCharles.Forsyth
22*37da2899SCharles.ForsythobjIdTab = array [] of {
23*37da2899SCharles.Forsyth	id_pkcs =>			Oid(array [] of {1,2,840,113549,1}),
24*37da2899SCharles.Forsyth	id_pkcs_1 =>			Oid(array [] of {1,2,840,113549,1,1}),
25*37da2899SCharles.Forsyth	id_pkcs_rsaEncryption => 	Oid(array [] of {1,2,840,113549,1,1,1}),
26*37da2899SCharles.Forsyth	id_pkcs_md2WithRSAEncryption => Oid(array [] of {1,2,840,113549,1,1,2}),
27*37da2899SCharles.Forsyth	id_pkcs_md4WithRSAEncryption => Oid(array [] of {1,2,840,113549,1,1,3}),
28*37da2899SCharles.Forsyth	id_pkcs_md5WithRSAEncryption =>	Oid(array [] of {1,2,840,113549,1,1,4}),
29*37da2899SCharles.Forsyth
30*37da2899SCharles.Forsyth	id_pkcs_3 =>			Oid(array [] of {1,2,840,113549,1,3}),
31*37da2899SCharles.Forsyth	id_pkcs_dhKeyAgreement =>	Oid(array [] of {1,2,840,113549,1,3,1}),
32*37da2899SCharles.Forsyth
33*37da2899SCharles.Forsyth	id_pkcs_5 =>			Oid(array [] of {1,2,840,113549,1,5}),
34*37da2899SCharles.Forsyth	id_pkcs_pbeWithMD2AndDESCBC => 	Oid(array [] of {1,2,840,113549,1,5,1}),
35*37da2899SCharles.Forsyth	id_pkcs_pbeWithMD5AndDESCBC =>	Oid(array [] of {1,2,840,113549,1,5,3}),
36*37da2899SCharles.Forsyth
37*37da2899SCharles.Forsyth	id_pkcs_7 =>			Oid(array [] of {1,2,840,113549,1,7}),
38*37da2899SCharles.Forsyth	id_pkcs_data =>			Oid(array [] of {1,2,840,113549,1,7,1}),
39*37da2899SCharles.Forsyth	id_pkcs_singnedData => 		Oid(array [] of {1,2,840,113549,1,7,2}),
40*37da2899SCharles.Forsyth	id_pkcs_envelopedData =>	Oid(array [] of {1,2,840,113549,1,7,3}),
41*37da2899SCharles.Forsyth	id_pkcs_signedAndEnvelopedData =>
42*37da2899SCharles.Forsyth					Oid(array [] of {1,2,840,113549,1,7,4}),
43*37da2899SCharles.Forsyth	id_pkcs_digestData =>		Oid(array [] of {1,2,840,113549,1,7,5}),
44*37da2899SCharles.Forsyth	id_pkcs_encryptedData =>	Oid(array [] of {1,2,840,113549,1,7,6}),
45*37da2899SCharles.Forsyth
46*37da2899SCharles.Forsyth	id_pkcs_9 =>			Oid(array [] of {1,2,840,113549,1,9}),
47*37da2899SCharles.Forsyth	id_pkcs_emailAddress => 	Oid(array [] of {1,2,840,113549,1,9,1}),
48*37da2899SCharles.Forsyth	id_pkcs_unstructuredName =>	Oid(array [] of {1,2,840,113549,1,9,2}),
49*37da2899SCharles.Forsyth	id_pkcs_contentType =>		Oid(array [] of {1,2,840,113549,1,9,3}),
50*37da2899SCharles.Forsyth	id_pkcs_messageDigest =>	Oid(array [] of {1,2,840,113549,1,9,4}),
51*37da2899SCharles.Forsyth	id_pkcs_signingTime =>		Oid(array [] of {1,2,840,113549,1,9,5}),
52*37da2899SCharles.Forsyth	id_pkcs_countersignature =>	Oid(array [] of {1,2,840,113549,1,9,6}),
53*37da2899SCharles.Forsyth	id_pkcs_challengePassword =>	Oid(array [] of {1,2,840,113549,1,9,7}),
54*37da2899SCharles.Forsyth	id_pkcs_unstructuredAddress =>	Oid(array [] of {1,2,840,113549,1,9,8}),
55*37da2899SCharles.Forsyth	id_pkcs_extCertAttrs =>		Oid(array [] of {1,2,840,113549,1,9,9}),
56*37da2899SCharles.Forsyth	id_algorithm_shaWithDSS =>	Oid(array [] of {1,3,14,3,2,13})
57*37da2899SCharles.Forsyth};
58*37da2899SCharles.Forsyth
59*37da2899SCharles.Forsyth# [public]
60*37da2899SCharles.Forsyth# initialize PKCS module
61*37da2899SCharles.Forsyth
62*37da2899SCharles.Forsythinit(): string
63*37da2899SCharles.Forsyth{
64*37da2899SCharles.Forsyth	sys = load Sys Sys->PATH;
65*37da2899SCharles.Forsyth	if(sys == nil)
66*37da2899SCharles.Forsyth		return "load sys module failed";
67*37da2899SCharles.Forsyth
68*37da2899SCharles.Forsyth	keyring = load Keyring Keyring->PATH;
69*37da2899SCharles.Forsyth	if(keyring == nil)
70*37da2899SCharles.Forsyth		return "load keyring module failed";
71*37da2899SCharles.Forsyth
72*37da2899SCharles.Forsyth	random = load Random Random->PATH;
73*37da2899SCharles.Forsyth	if(random == nil)
74*37da2899SCharles.Forsyth		return "load random module failed";
75*37da2899SCharles.Forsyth
76*37da2899SCharles.Forsyth	asn1 = load ASN1 ASN1->PATH;
77*37da2899SCharles.Forsyth	if(asn1 == nil)
78*37da2899SCharles.Forsyth		return "load asn1 module failed";
79*37da2899SCharles.Forsyth	asn1->init();
80*37da2899SCharles.Forsyth
81*37da2899SCharles.Forsyth	return "";
82*37da2899SCharles.Forsyth}
83*37da2899SCharles.Forsyth
84*37da2899SCharles.Forsyth# [public]
85*37da2899SCharles.Forsyth# Encrypt data according to PKCS#1, with given blocktype, using given key.
86*37da2899SCharles.Forsyth
87*37da2899SCharles.Forsythrsa_encrypt(data: array of byte, key: ref RSAKey, blocktype: int)
88*37da2899SCharles.Forsyth	: (string, array of byte)
89*37da2899SCharles.Forsyth{
90*37da2899SCharles.Forsyth	if(key == nil)
91*37da2899SCharles.Forsyth		return ("null pkcs#1 key", nil);
92*37da2899SCharles.Forsyth	k := key.modlen;
93*37da2899SCharles.Forsyth	dlen := len data;
94*37da2899SCharles.Forsyth	if(k < 12 || dlen > k-11)
95*37da2899SCharles.Forsyth		return ("bad parameters for pkcs#1", nil);
96*37da2899SCharles.Forsyth	padlen := k-3-dlen;
97*37da2899SCharles.Forsyth	pad := random->randombuf(Random->NotQuiteRandom, padlen);
98*37da2899SCharles.Forsyth	for(i:=0; i < padlen; i++) {
99*37da2899SCharles.Forsyth		if(blocktype == 0)
100*37da2899SCharles.Forsyth			pad[i] = byte 0;
101*37da2899SCharles.Forsyth		else if(blocktype == 1)
102*37da2899SCharles.Forsyth			pad[i] = byte 16rff;
103*37da2899SCharles.Forsyth		else if(pad[i] == byte 0)
104*37da2899SCharles.Forsyth			pad[i] = byte 1;
105*37da2899SCharles.Forsyth	}
106*37da2899SCharles.Forsyth	eb := array[k] of byte;
107*37da2899SCharles.Forsyth	eb[0] = byte 0;
108*37da2899SCharles.Forsyth	eb[1] = byte blocktype;
109*37da2899SCharles.Forsyth	eb[2:] = pad[0:];
110*37da2899SCharles.Forsyth	eb[padlen+2] = byte 0;
111*37da2899SCharles.Forsyth	eb[padlen+3:] = data[0:];
112*37da2899SCharles.Forsyth	return ("", rsacomp(eb, key));
113*37da2899SCharles.Forsyth}
114*37da2899SCharles.Forsyth
115*37da2899SCharles.Forsyth# [public]
116*37da2899SCharles.Forsyth# Decrypt data according to PKCS#1, with given key.
117*37da2899SCharles.Forsyth# If public is true, expect a block type of 0 or 1, else 2.
118*37da2899SCharles.Forsyth
119*37da2899SCharles.Forsythrsa_decrypt(data: array of byte, key: ref RSAKey, public: int)
120*37da2899SCharles.Forsyth	: (string, array of byte)
121*37da2899SCharles.Forsyth{
122*37da2899SCharles.Forsyth	eb := rsacomp(data, key);
123*37da2899SCharles.Forsyth	k := key.modlen;
124*37da2899SCharles.Forsyth	if(len eb == k) {
125*37da2899SCharles.Forsyth		bt := int eb[1];
126*37da2899SCharles.Forsyth		if(int eb[0] == 0 && ((public && (bt == 0 || bt == 1)) || (!public && bt == 2))) {
127*37da2899SCharles.Forsyth			for(i := 2; i < k; i++)
128*37da2899SCharles.Forsyth				if(eb[i] == byte 0)
129*37da2899SCharles.Forsyth					break;
130*37da2899SCharles.Forsyth			if(i < k-1) {
131*37da2899SCharles.Forsyth				ans := array[k-(i+1)] of byte;
132*37da2899SCharles.Forsyth				ans[0:] = eb[i+1:];
133*37da2899SCharles.Forsyth				return ("", ans);
134*37da2899SCharles.Forsyth			}
135*37da2899SCharles.Forsyth		}
136*37da2899SCharles.Forsyth	}
137*37da2899SCharles.Forsyth	return ("pkcs1 decryption error", nil);
138*37da2899SCharles.Forsyth}
139*37da2899SCharles.Forsyth
140*37da2899SCharles.Forsyth# [private]
141*37da2899SCharles.Forsyth# Do RSA computation on block according to key, and pad
142*37da2899SCharles.Forsyth# result on left with zeros to make it key.modlen long.
143*37da2899SCharles.Forsyth
144*37da2899SCharles.Forsythrsacomp(block: array of byte, key: ref RSAKey): array of byte
145*37da2899SCharles.Forsyth{
146*37da2899SCharles.Forsyth	x := keyring->IPint.bebytestoip(block);
147*37da2899SCharles.Forsyth	y := x.expmod(key.exponent, key.modulus);
148*37da2899SCharles.Forsyth	ybytes := y.iptobebytes();
149*37da2899SCharles.Forsyth	k := key.modlen;
150*37da2899SCharles.Forsyth	ylen := len ybytes;
151*37da2899SCharles.Forsyth	if(ylen < k) {
152*37da2899SCharles.Forsyth		a := array[k] of { * =>  byte 0};
153*37da2899SCharles.Forsyth		a[k-ylen:] = ybytes[0:];
154*37da2899SCharles.Forsyth		ybytes = a;
155*37da2899SCharles.Forsyth	}
156*37da2899SCharles.Forsyth	else if(ylen > k) {
157*37da2899SCharles.Forsyth		# assume it has leading zeros (mod should make it so)
158*37da2899SCharles.Forsyth		a := array[k] of byte;
159*37da2899SCharles.Forsyth		a[0:] = ybytes[ylen-k:];
160*37da2899SCharles.Forsyth		ybytes = a;
161*37da2899SCharles.Forsyth	}
162*37da2899SCharles.Forsyth	return ybytes;
163*37da2899SCharles.Forsyth}
164*37da2899SCharles.Forsyth
165*37da2899SCharles.Forsyth# [public]
166*37da2899SCharles.Forsyth
167*37da2899SCharles.Forsythrsa_sign(data: array of byte, sk: ref RSAKey, algid: int): (string, array of byte)
168*37da2899SCharles.Forsyth{
169*37da2899SCharles.Forsyth	# digesting and add proper padding to it
170*37da2899SCharles.Forsyth	ph := padhash(data, algid);
171*37da2899SCharles.Forsyth
172*37da2899SCharles.Forsyth	return rsa_encrypt(ph, sk, 0); # blocktype <- padding with zero
173*37da2899SCharles.Forsyth}
174*37da2899SCharles.Forsyth
175*37da2899SCharles.Forsyth# [public]
176*37da2899SCharles.Forsyth
177*37da2899SCharles.Forsythrsa_verify(data, signature: array of byte, pk: ref RSAKey, algid: int): int
178*37da2899SCharles.Forsyth{
179*37da2899SCharles.Forsyth	# digesting and add proper padding to it
180*37da2899SCharles.Forsyth	ph := padhash(data, algid);
181*37da2899SCharles.Forsyth
182*37da2899SCharles.Forsyth	(err, orig) := rsa_decrypt(signature, pk, 0); # blocktype ?
183*37da2899SCharles.Forsyth	if(err != "" || !byte_cmp(orig, ph))
184*37da2899SCharles.Forsyth		return 0;
185*37da2899SCharles.Forsyth
186*37da2899SCharles.Forsyth	return 1;
187*37da2899SCharles.Forsyth}
188*37da2899SCharles.Forsyth
189*37da2899SCharles.Forsyth# [private]
190*37da2899SCharles.Forsyth# padding block A
191*37da2899SCharles.ForsythPA := array [] of {
192*37da2899SCharles.Forsyth	byte 16r30, byte 16r20, byte 16r30, byte 16r0c,
193*37da2899SCharles.Forsyth	byte 16r06, byte 16r08, byte 16r2a, byte 16r86,
194*37da2899SCharles.Forsyth	byte 16r48, byte 16r86, byte 16rf7, byte 16r0d,
195*37da2899SCharles.Forsyth	byte 16r02
196*37da2899SCharles.Forsyth};
197*37da2899SCharles.Forsyth
198*37da2899SCharles.Forsyth# [private]
199*37da2899SCharles.Forsyth# padding block B
200*37da2899SCharles.ForsythPB := array [] of {byte 16r05, byte 16r00, byte 16r04, byte 16r10};
201*37da2899SCharles.Forsyth
202*37da2899SCharles.Forsyth# [private]
203*37da2899SCharles.Forsyth# require either md5 or md2 of 16 bytes digest
204*37da2899SCharles.Forsyth# length of padded digest = 13 + 1 + 4 + 16
205*37da2899SCharles.Forsyth
206*37da2899SCharles.Forsythpadhash(data: array of byte, algid: int): array of byte
207*37da2899SCharles.Forsyth{
208*37da2899SCharles.Forsyth	padded := array [34] of byte;
209*37da2899SCharles.Forsyth	case algid {
210*37da2899SCharles.Forsyth	MD2_WithRSAEncryption =>
211*37da2899SCharles.Forsyth		padded[13] = byte 2;
212*37da2899SCharles.Forsyth		# TODO: implement md2 in keyring module
213*37da2899SCharles.Forsyth		# keyring->md2(data, len data, padded[18:], nil);
214*37da2899SCharles.Forsyth
215*37da2899SCharles.Forsyth	MD5_WithRSAEncryption =>
216*37da2899SCharles.Forsyth		padded[13] = byte 5;
217*37da2899SCharles.Forsyth		keyring->md5(data, len data, padded[18:], nil);
218*37da2899SCharles.Forsyth	* =>
219*37da2899SCharles.Forsyth		return nil;
220*37da2899SCharles.Forsyth	}
221*37da2899SCharles.Forsyth	padded[0:] = PA;
222*37da2899SCharles.Forsyth	padded[14:] = PB;
223*37da2899SCharles.Forsyth
224*37da2899SCharles.Forsyth	return padded;
225*37da2899SCharles.Forsyth}
226*37da2899SCharles.Forsyth
227*37da2899SCharles.Forsyth# [private]
228*37da2899SCharles.Forsyth# compare byte to byte of two array of byte
229*37da2899SCharles.Forsyth
230*37da2899SCharles.Forsythbyte_cmp(a, b: array of byte): int
231*37da2899SCharles.Forsyth{
232*37da2899SCharles.Forsyth	if(len a != len b)
233*37da2899SCharles.Forsyth		return 0;
234*37da2899SCharles.Forsyth
235*37da2899SCharles.Forsyth	for(i := 0; i < len a; i++) {
236*37da2899SCharles.Forsyth		if(a[i] != b[i])
237*37da2899SCharles.Forsyth			return 0;
238*37da2899SCharles.Forsyth	}
239*37da2899SCharles.Forsyth
240*37da2899SCharles.Forsyth	return 1;
241*37da2899SCharles.Forsyth}
242*37da2899SCharles.Forsyth
243*37da2899SCharles.Forsyth# [public]
244*37da2899SCharles.Forsyth
245*37da2899SCharles.ForsythRSAKey.bits(key: self ref RSAKey): int
246*37da2899SCharles.Forsyth{
247*37da2899SCharles.Forsyth	return key.modulus.bits();
248*37da2899SCharles.Forsyth}
249*37da2899SCharles.Forsyth
250*37da2899SCharles.Forsyth# [public]
251*37da2899SCharles.Forsyth# Decode an RSAPublicKey ASN1 type, defined as:
252*37da2899SCharles.Forsyth#
253*37da2899SCharles.Forsyth#	RSAPublickKey :: SEQUENCE {
254*37da2899SCharles.Forsyth#		modulus INTEGER,
255*37da2899SCharles.Forsyth#		publicExponent INTEGER
256*37da2899SCharles.Forsyth#	}
257*37da2899SCharles.Forsyth
258*37da2899SCharles.Forsythdecode_rsapubkey(a: array of byte): (string, ref RSAKey)
259*37da2899SCharles.Forsyth{
260*37da2899SCharles.Forsythparse:
261*37da2899SCharles.Forsyth	for(;;) {
262*37da2899SCharles.Forsyth		(err, e) := asn1->decode(a);
263*37da2899SCharles.Forsyth		if(err != "")
264*37da2899SCharles.Forsyth			break parse;
265*37da2899SCharles.Forsyth		(ok, el) := e.is_seq();
266*37da2899SCharles.Forsyth		if(!ok || len el != 2)
267*37da2899SCharles.Forsyth			break parse;
268*37da2899SCharles.Forsyth		modbytes, expbytes: array of byte;
269*37da2899SCharles.Forsyth		(ok, modbytes) = (hd el).is_bigint();
270*37da2899SCharles.Forsyth		if(!ok)
271*37da2899SCharles.Forsyth			break parse;
272*37da2899SCharles.Forsyth		modulus := IPint.bebytestoip(modbytes);
273*37da2899SCharles.Forsyth		# get modlen this way, because sometimes it
274*37da2899SCharles.Forsyth		# comes with leading zeros that are to be ignored!
275*37da2899SCharles.Forsyth		mbytes := modulus.iptobebytes();
276*37da2899SCharles.Forsyth		modlen := len mbytes;
277*37da2899SCharles.Forsyth		(ok, expbytes) = (hd tl el).is_bigint();
278*37da2899SCharles.Forsyth		if(!ok)
279*37da2899SCharles.Forsyth			break parse;
280*37da2899SCharles.Forsyth		exponent := keyring->IPint.bebytestoip(expbytes);
281*37da2899SCharles.Forsyth		return ("", ref RSAKey(modulus, modlen, exponent));
282*37da2899SCharles.Forsyth	}
283*37da2899SCharles.Forsyth	return ("rsa public key: syntax error", nil);
284*37da2899SCharles.Forsyth}
285*37da2899SCharles.Forsyth
286*37da2899SCharles.Forsyth
287*37da2899SCharles.Forsyth# [public]
288*37da2899SCharles.Forsyth# generate a pair of DSS public and private keys
289*37da2899SCharles.Forsyth
290*37da2899SCharles.ForsythgenerateDSSKeyPair(strength: int): (ref DSSPublicKey, ref DSSPrivateKey)
291*37da2899SCharles.Forsyth{
292*37da2899SCharles.Forsyth	# TODO: need add getRandBetween in IPint
293*37da2899SCharles.Forsyth	return (nil, nil);
294*37da2899SCharles.Forsyth}
295*37da2899SCharles.Forsyth
296*37da2899SCharles.Forsyth# [public]
297*37da2899SCharles.Forsyth
298*37da2899SCharles.Forsythdss_sign(a: array of byte, sk: ref DSSPrivateKey): (string, array of byte)
299*37da2899SCharles.Forsyth{
300*37da2899SCharles.Forsyth	#signature, digest: array of byte;
301*37da2899SCharles.Forsyth
302*37da2899SCharles.Forsyth	#case hash {
303*37da2899SCharles.Forsyth	#Keyring->MD4 =>
304*37da2899SCharles.Forsyth	#	digest = array [Keyring->MD4dlen] of byte;
305*37da2899SCharles.Forsyth	#	keyring->md4(a, len a, digest, nil);
306*37da2899SCharles.Forsyth	#Keyring->MD5 =>
307*37da2899SCharles.Forsyth	#	digest = array [Keyring->MD5dlen] of byte;
308*37da2899SCharles.Forsyth	#	keyring->md5(a, len a, digest, nil);
309*37da2899SCharles.Forsyth	#Keyring->SHA =>
310*37da2899SCharles.Forsyth	#	digest = array [Keyring->SHA1dlen] of byte;
311*37da2899SCharles.Forsyth	#	keyring->sha1(a, len a, digest, nil);
312*37da2899SCharles.Forsyth	#* =>
313*37da2899SCharles.Forsyth	#	return ("unknown hash algorithm", nil);
314*37da2899SCharles.Forsyth	#}
315*37da2899SCharles.Forsyth
316*37da2899SCharles.Forsyth	# TODO: add gcd or getRandBetween in Keyring->IPint
317*37da2899SCharles.Forsyth	return ("unsupported error", nil);
318*37da2899SCharles.Forsyth}
319*37da2899SCharles.Forsyth
320*37da2899SCharles.Forsyth# [public]
321*37da2899SCharles.Forsyth
322*37da2899SCharles.Forsythdss_verify(a, signa: array of byte, pk: ref DSSPublicKey): int
323*37da2899SCharles.Forsyth{
324*37da2899SCharles.Forsyth	unsigned: array of byte;
325*37da2899SCharles.Forsyth
326*37da2899SCharles.Forsyth	#case hash {
327*37da2899SCharles.Forsyth	#Keyring->MD4 =>
328*37da2899SCharles.Forsyth	#	digest = array [Keyring->MD4dlen] of byte;
329*37da2899SCharles.Forsyth	#	keyring->md4(a, len a, digest, nil);
330*37da2899SCharles.Forsyth	#Keyring->MD5 =>
331*37da2899SCharles.Forsyth	#	digest = array [Keyring->MD5dlen] of byte;
332*37da2899SCharles.Forsyth	#	keyring->md5(a, len a, digest, nil);
333*37da2899SCharles.Forsyth	#Keyring->SHA =>
334*37da2899SCharles.Forsyth	#	digest = array [Keyring->SHA1dlen] of byte;
335*37da2899SCharles.Forsyth	#	keyring->sha1(a, len a, digest, nil);
336*37da2899SCharles.Forsyth	#* =>
337*37da2899SCharles.Forsyth	#	return 0;
338*37da2899SCharles.Forsyth	#}
339*37da2899SCharles.Forsyth
340*37da2899SCharles.Forsyth	# get unsigned from signa and compare it with digest
341*37da2899SCharles.Forsyth
342*37da2899SCharles.Forsyth	if(byte_cmp(unsigned, a))
343*37da2899SCharles.Forsyth		return 1;
344*37da2899SCharles.Forsyth
345*37da2899SCharles.Forsyth	return 0;
346*37da2899SCharles.Forsyth}
347*37da2899SCharles.Forsyth
348*37da2899SCharles.Forsyth# [public]
349*37da2899SCharles.Forsythdecode_dsspubkey(a: array of byte): (string, ref DSSPublicKey)
350*37da2899SCharles.Forsyth{
351*37da2899SCharles.Forsyth	return ("unsupported error", nil);
352*37da2899SCharles.Forsyth}
353*37da2899SCharles.Forsyth
354*37da2899SCharles.Forsyth
355*37da2899SCharles.Forsyth# [public]
356*37da2899SCharles.Forsyth# generate DH parameters with prime length at least (default) 512 bits
357*37da2899SCharles.Forsyth
358*37da2899SCharles.ForsythgenerateDHParams(primelen: int): ref DHParams
359*37da2899SCharles.Forsyth{
360*37da2899SCharles.Forsyth	# prime - at least 512 bits
361*37da2899SCharles.Forsyth	if(primelen < 512) # DHmodlen
362*37da2899SCharles.Forsyth		primelen = 512;
363*37da2899SCharles.Forsyth
364*37da2899SCharles.Forsyth	# generate prime and base (generator) integers
365*37da2899SCharles.Forsyth	(p, g) := keyring->dhparams(primelen);
366*37da2899SCharles.Forsyth	if(p == nil || g == nil)
367*37da2899SCharles.Forsyth		return nil;
368*37da2899SCharles.Forsyth
369*37da2899SCharles.Forsyth	return ref DHParams(p, g, 0);
370*37da2899SCharles.Forsyth}
371*37da2899SCharles.Forsyth
372*37da2899SCharles.Forsyth# [public]
373*37da2899SCharles.Forsyth# generate public and private key pair
374*37da2899SCharles.Forsyth# Note: use iptobytes as integer to octet string conversion
375*37da2899SCharles.Forsyth#	and bytestoip as octect string to integer reversion
376*37da2899SCharles.Forsyth
377*37da2899SCharles.ForsythsetupDHAgreement(dh: ref DHParams): (ref DHPrivateKey, ref DHPublicKey)
378*37da2899SCharles.Forsyth{
379*37da2899SCharles.Forsyth	if(dh == nil || dh.prime == nil || dh.base == nil)
380*37da2899SCharles.Forsyth		return (nil, nil);
381*37da2899SCharles.Forsyth
382*37da2899SCharles.Forsyth	# prime length in bits
383*37da2899SCharles.Forsyth	bits := dh.prime.bits();
384*37da2899SCharles.Forsyth
385*37da2899SCharles.Forsyth	# generate random private key of length between bits/4 and bits
386*37da2899SCharles.Forsyth	x := IPint.random(bits/4, bits);
387*37da2899SCharles.Forsyth	if(x == nil)
388*37da2899SCharles.Forsyth		return (nil, nil);
389*37da2899SCharles.Forsyth	dh.privateValueLength = x.bits();
390*37da2899SCharles.Forsyth
391*37da2899SCharles.Forsyth	# calculate public key
392*37da2899SCharles.Forsyth	y := dh.base.expmod(x, dh.prime);
393*37da2899SCharles.Forsyth	if(y == nil)
394*37da2899SCharles.Forsyth		return (nil, nil);
395*37da2899SCharles.Forsyth
396*37da2899SCharles.Forsyth	return (ref DHPrivateKey(dh, y, x), ref DHPublicKey(dh, x));
397*37da2899SCharles.Forsyth}
398*37da2899SCharles.Forsyth
399*37da2899SCharles.Forsyth# [public]
400*37da2899SCharles.Forsyth# The second phase of Diffie-Hellman key agreement
401*37da2899SCharles.Forsyth
402*37da2899SCharles.ForsythcomputeDHAgreedKey(dh: ref DHParams, mysk, upk: ref IPint)
403*37da2899SCharles.Forsyth	: array of byte
404*37da2899SCharles.Forsyth{
405*37da2899SCharles.Forsyth	if(mysk == nil || upk == nil)
406*37da2899SCharles.Forsyth		return nil;
407*37da2899SCharles.Forsyth
408*37da2899SCharles.Forsyth	# exponential - calculate agreed key (shared secret)
409*37da2899SCharles.Forsyth	z := upk.expmod(mysk, dh.prime);
410*37da2899SCharles.Forsyth
411*37da2899SCharles.Forsyth	# integer to octet conversion
412*37da2899SCharles.Forsyth	return z.iptobebytes();
413*37da2899SCharles.Forsyth}
414*37da2899SCharles.Forsyth
415*37da2899SCharles.Forsyth# [public]
416*37da2899SCharles.Forsyth# ASN1 encoding
417*37da2899SCharles.Forsyth
418*37da2899SCharles.Forsythdecode_dhpubkey(a: array of byte): (string, ref DHPublicKey)
419*37da2899SCharles.Forsyth{
420*37da2899SCharles.Forsyth	return ("unsupported error", nil);
421*37da2899SCharles.Forsyth}
422*37da2899SCharles.Forsyth
423*37da2899SCharles.Forsyth
424*37da2899SCharles.Forsyth# [public]
425*37da2899SCharles.Forsyth# Digest the concatenation of password and salt with count iterations of
426*37da2899SCharles.Forsyth# selected message-digest algorithm (either md2 or md5).
427*37da2899SCharles.Forsyth# The first 8 bytes of the message digest become the DES key.
428*37da2899SCharles.Forsyth# The last 8 bytes of the message digest become the initializing vector IV.
429*37da2899SCharles.Forsyth
430*37da2899SCharles.ForsythgenerateDESKey(pw: array of byte, param: ref PBEParams, alg: int)
431*37da2899SCharles.Forsyth	: (ref DESstate, array of byte, array of byte)
432*37da2899SCharles.Forsyth{
433*37da2899SCharles.Forsyth	if(param.iterationCount < 1)
434*37da2899SCharles.Forsyth		return (nil, nil, nil);
435*37da2899SCharles.Forsyth
436*37da2899SCharles.Forsyth	# concanate password and salt
437*37da2899SCharles.Forsyth	pwlen := len pw;
438*37da2899SCharles.Forsyth	pslen := pwlen + len param.salt;
439*37da2899SCharles.Forsyth	ps := array [pslen] of byte;
440*37da2899SCharles.Forsyth	ps[0:] = pw;
441*37da2899SCharles.Forsyth	ps[pwlen:] = param.salt;
442*37da2899SCharles.Forsyth	key, iv: array of byte;
443*37da2899SCharles.Forsyth
444*37da2899SCharles.Forsyth	# digest iterations
445*37da2899SCharles.Forsyth	case alg {
446*37da2899SCharles.Forsyth	PBE_MD2_DESCBC =>
447*37da2899SCharles.Forsyth		ds : ref Keyring->DigestState = nil;
448*37da2899SCharles.Forsyth		# TODO: implement md2 in keyring module
449*37da2899SCharles.Forsyth		#result := array [Keyring->MD2dlen] of byte;
450*37da2899SCharles.Forsyth		#for(i := 0; i < param.iterationCount; i++)
451*37da2899SCharles.Forsyth		#	ds = keyring->md2(ps, pslen, nil, ds);
452*37da2899SCharles.Forsyth		#keyring->md2(ps, pslen, result, ds);
453*37da2899SCharles.Forsyth		#key = result[0:8];
454*37da2899SCharles.Forsyth		#iv = result[8:];
455*37da2899SCharles.Forsyth
456*37da2899SCharles.Forsyth	PBE_MD5_DESCBC =>
457*37da2899SCharles.Forsyth		ds: ref Keyring->DigestState = nil;
458*37da2899SCharles.Forsyth		result := array [Keyring->MD5dlen] of byte;
459*37da2899SCharles.Forsyth		for(i := 0; i < param.iterationCount; i++)
460*37da2899SCharles.Forsyth			ds = keyring->md5(ps, pslen, nil, ds);
461*37da2899SCharles.Forsyth		keyring->md5(ps, pslen, result, ds);
462*37da2899SCharles.Forsyth		key = result[0:8];
463*37da2899SCharles.Forsyth		iv = result[8:];
464*37da2899SCharles.Forsyth
465*37da2899SCharles.Forsyth	* =>
466*37da2899SCharles.Forsyth		return (nil, nil, nil);
467*37da2899SCharles.Forsyth	}
468*37da2899SCharles.Forsyth
469*37da2899SCharles.Forsyth	state := keyring->dessetup(key, iv);
470*37da2899SCharles.Forsyth
471*37da2899SCharles.Forsyth	return (state, key, iv);
472*37da2899SCharles.Forsyth}
473*37da2899SCharles.Forsyth
474*37da2899SCharles.Forsyth# [public]
475*37da2899SCharles.Forsyth# The message M and a padding string PS shall be formatted into
476*37da2899SCharles.Forsyth# an octet string EB
477*37da2899SCharles.Forsyth# 	EB = M + PS
478*37da2899SCharles.Forsyth# where
479*37da2899SCharles.Forsyth#	PS = 1 if M mod 8 = 7;
480*37da2899SCharles.Forsyth#	PS = 2 + 2 if M mod 8 = 6;
481*37da2899SCharles.Forsyth#	...
482*37da2899SCharles.Forsyth#	PS = 8 + 8 + 8 + 8 + 8 + 8 + 8 + 8 if M mod 8 = 0;
483*37da2899SCharles.Forsyth
484*37da2899SCharles.Forsythpbe_encrypt(state: ref DESstate, m: array of byte): array of byte
485*37da2899SCharles.Forsyth{
486*37da2899SCharles.Forsyth	mlen := len m;
487*37da2899SCharles.Forsyth	padvalue :=  mlen % 8;
488*37da2899SCharles.Forsyth	pdlen := 8 - padvalue;
489*37da2899SCharles.Forsyth
490*37da2899SCharles.Forsyth	eb := array [mlen + pdlen] of byte;
491*37da2899SCharles.Forsyth	eb[0:] = m;
492*37da2899SCharles.Forsyth	for(i := mlen; i < pdlen; i++)
493*37da2899SCharles.Forsyth		eb[i] = byte padvalue;
494*37da2899SCharles.Forsyth
495*37da2899SCharles.Forsyth	keyring->descbc(state, eb, len eb, Keyring->Encrypt);
496*37da2899SCharles.Forsyth
497*37da2899SCharles.Forsyth	return eb;
498*37da2899SCharles.Forsyth}
499*37da2899SCharles.Forsyth
500*37da2899SCharles.Forsyth# [public]
501*37da2899SCharles.Forsyth
502*37da2899SCharles.Forsythpbe_decrypt(state: ref DESstate, eb: array of byte): array of byte
503*37da2899SCharles.Forsyth{
504*37da2899SCharles.Forsyth	eblen := len eb;
505*37da2899SCharles.Forsyth	if(eblen%8 != 0) # must a multiple of 8 bytes
506*37da2899SCharles.Forsyth		return nil;
507*37da2899SCharles.Forsyth
508*37da2899SCharles.Forsyth	keyring->descbc(state, eb, eblen, Keyring->Decrypt);
509*37da2899SCharles.Forsyth
510*37da2899SCharles.Forsyth	# remove padding
511*37da2899SCharles.Forsyth	for(i := eblen -8; i < 8; i++) {
512*37da2899SCharles.Forsyth		if(int eb[i] == i) {
513*37da2899SCharles.Forsyth			for(j := i; j < 8; j++)
514*37da2899SCharles.Forsyth				if(int eb[j] != i)
515*37da2899SCharles.Forsyth					break;
516*37da2899SCharles.Forsyth			if(j == 8)
517*37da2899SCharles.Forsyth				break;
518*37da2899SCharles.Forsyth		}
519*37da2899SCharles.Forsyth	}
520*37da2899SCharles.Forsyth
521*37da2899SCharles.Forsyth	return eb[0:i];
522*37da2899SCharles.Forsyth}
523*37da2899SCharles.Forsyth
524*37da2899SCharles.Forsyth# [public]
525*37da2899SCharles.Forsyth
526*37da2899SCharles.ForsythPrivateKeyInfo.encode(p: self ref PrivateKeyInfo): (string, array of byte)
527*37da2899SCharles.Forsyth{
528*37da2899SCharles.Forsyth
529*37da2899SCharles.Forsyth	return ("unsupported error", nil);
530*37da2899SCharles.Forsyth}
531*37da2899SCharles.Forsyth
532*37da2899SCharles.Forsyth# [public]
533*37da2899SCharles.Forsyth
534*37da2899SCharles.ForsythPrivateKeyInfo.decode(a: array of byte): (string, ref PrivateKeyInfo)
535*37da2899SCharles.Forsyth{
536*37da2899SCharles.Forsyth	return ("unsupported error", nil);
537*37da2899SCharles.Forsyth}
538*37da2899SCharles.Forsyth
539*37da2899SCharles.Forsyth# [public]
540*37da2899SCharles.Forsyth
541*37da2899SCharles.ForsythEncryptedPrivateKeyInfo.encode(p: self ref EncryptedPrivateKeyInfo)
542*37da2899SCharles.Forsyth	: (string, array of byte)
543*37da2899SCharles.Forsyth{
544*37da2899SCharles.Forsyth
545*37da2899SCharles.Forsyth	return ("unsupported error", nil);
546*37da2899SCharles.Forsyth}
547*37da2899SCharles.Forsyth
548*37da2899SCharles.Forsyth# [public]
549*37da2899SCharles.Forsyth
550*37da2899SCharles.ForsythEncryptedPrivateKeyInfo.decode(a: array of byte)
551*37da2899SCharles.Forsyth	: (string, ref EncryptedPrivateKeyInfo)
552*37da2899SCharles.Forsyth{
553*37da2899SCharles.Forsyth	return ("unsupported error", nil);
554*37da2899SCharles.Forsyth}
555*37da2899SCharles.Forsyth
556*37da2899SCharles.Forsyth# [public]
557*37da2899SCharles.Forsyth
558*37da2899SCharles.Forsythdecode_extcertorcert(a: array of byte): (int, int, array of byte)
559*37da2899SCharles.Forsyth{
560*37da2899SCharles.Forsyth	(err, all) := asn1->decode(a);
561*37da2899SCharles.Forsyth	if(err == "") {
562*37da2899SCharles.Forsyth
563*37da2899SCharles.Forsyth	}
564*37da2899SCharles.Forsyth}
565*37da2899SCharles.Forsyth
566*37da2899SCharles.Forsyth# [public]
567*37da2899SCharles.Forsyth
568*37da2899SCharles.Forsythencode_extcertorcert(a: array of byte, which: int): (int, array of byte)
569*37da2899SCharles.Forsyth{
570*37da2899SCharles.Forsyth
571*37da2899SCharles.Forsyth}
572*37da2899SCharles.Forsyth
573