1//
2//  test_encrypt.c
3//  OpenSSH
4//
5//  Created by Rab Hagy on 2/4/13.
6//
7//
8
9#include <sys/types.h>
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#include <getopt.h>
14
15#include <errno.h>
16#include <fcntl.h>
17#include <stdarg.h>
18#include <stdio.h>
19#include <stdlib.h>
20#include <unistd.h>
21
22
23#include <sys/time.h>
24
25#include "config.h"
26
27#ifdef __APPLE_CRYPTO__
28#include "ossl-config.h"
29
30#include "ossl-crypto.h"
31
32#include "ossl-objects.h"
33#include "ossl-engine.h"
34#include "ossl-evp.h"
35#include "ossl-err.h"
36#include "ossl-pem.h"
37#include "ossl-rsa.h"
38#include "ossl-bio.h"
39#else
40#warning Using OpenSSL headers
41#include <openssl/objects.h>
42#include <openssl/engine.h>
43#include <openssl/evp.h>
44#include <openssl/err.h>
45#include <openssl/pem.h>
46#include <openssl/rsa.h>
47#include <openssl/bio.h>
48#endif
49
50#include "cipher.h"
51
52/* compatibility with old or broken OpenSSL versions */
53// #include "openbsd-compat/openssl-compat.h"
54
55
56#include "xmalloc.h"
57#include "buffer.h"
58#include "key.h"
59#include "ssh.h"
60#include "log.h"
61#include "authfile.h"
62#include "misc.h"
63#include "atomicio.h"
64
65#define MAX_KEY_FILE_SIZE	(1024 * 1024)
66
67
68void
69error(const char *fmt,...)
70{
71	va_list args;
72
73	va_start(args, fmt);
74	fprintf(stderr, fmt, args);
75	va_end(args);
76}
77
78static void
79dump_bytes(const char *msg, void *bytes, size_t length)
80{
81	printf("\n%s (%lu bytes)\n", msg, length);
82
83	int numOut = 0;
84	char *b = bytes;
85
86
87	while (length-- > 0) {
88		printf("%2.2hhx", *b++);
89		if (++numOut > 40) {
90			printf("\n");
91			numOut = 0;
92		}
93	}
94
95	printf("\n\n\n");
96}
97
98static const char *
99pkey_str(EVP_PKEY *x)
100{
101	switch (x->type) {
102		case EVP_PKEY_RSA:
103			return (PEM_STRING_RSA);
104
105		case EVP_PKEY_DSA:
106			return (PEM_STRING_DSA);
107
108		default:
109			return (NULL);
110	}
111}
112
113
114int
115i2d_PrivateKey(EVP_PKEY *a, unsigned char **pp)
116{
117	if (a->type == EVP_PKEY_RSA) {
118		return (i2d_RSAPrivateKey(a->pkey.rsa, pp));
119	} else if (a->type == EVP_PKEY_DSA) {
120		return (i2d_DSAPrivateKey(a->pkey.dsa, pp));
121
122		return (-1);
123	}
124
125	return (-1);
126}
127
128int
129PEM_write_bio_PrivateKey(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc,
130			 unsigned char *kstr, int klen, pem_password_cb *callback, void *u)
131{
132
133	EVP_CIPHER_CTX ctx;
134	int dsize = 0, i, j, ret = 0;
135	unsigned char *p, *data = NULL;
136	const char *objstr = NULL;
137	const char *name = pkey_str(x);
138	char buf[PEM_BUFSIZE];
139	unsigned char key[EVP_MAX_KEY_LENGTH];
140	unsigned char iv[EVP_MAX_IV_LENGTH];
141
142	if (enc != NULL) {
143		objstr = OBJ_nid2sn(EVP_CIPHER_nid(enc));
144
145		if (objstr == NULL) {
146			/* PEMerr(PEM_F_PEM_ASN1_WRITE_BIO,PEM_R_UNSUPPORTED_CIPHER); */
147			goto err;
148		}
149	}
150
151	printf("key name: %s\n", name);
152	printf("obj str:  %s\n\n", objstr);
153
154	if ((dsize = i2d_PrivateKey(x, NULL)) < 0) {
155		/* PEMerr(PEM_F_PEM_ASN1_WRITE_BIO,ERR_R_ASN1_LIB); */
156		dsize = 0;
157		goto err;
158	}
159	/* dzise + 8 bytes are needed */
160	/* actually it needs the cipher block size extra... */
161	size_t data_buffer_size = (unsigned int)dsize + 20;
162	printf("data_buffer_size: %lu\n", data_buffer_size);
163
164	data = (unsigned char *)malloc((unsigned int)dsize + 20);
165	if (data == NULL) {
166		/* PEMerr(PEM_F_PEM_ASN1_WRITE_BIO,ERR_R_MALLOC_FAILURE); */
167		goto err;
168	}
169	memset(data, 0xee, dsize + 20);
170
171	p = data;
172	i = i2d_PrivateKey(x, &p);
173
174	dump_bytes("Private key data:", data, i);
175
176	if (enc != NULL) {
177		if (kstr == NULL) {
178			fprintf(stderr, "kstr password is NULL\n");
179			exit(1);
180		}
181
182		// RAND_add(data, i, 0); /* put in the RSA key. */
183
184		/* assert(enc->iv_len <= (int)sizeof(iv)); */
185#ifdef NOT_DEF
186		if (RAND_pseudo_bytes(iv, enc->iv_len) < 0) { /* Generate a salt */
187			goto err;
188		}
189#endif
190
191		printf("enc->iv_len: %d (EVP_MAX_IV_LENGTH: %d)\n", enc->iv_len, EVP_MAX_IV_LENGTH);
192		printf("enc->key_len: %d (EVP_MAX_KEY_LENGTH: %d)\n", enc->iv_len, EVP_MAX_KEY_LENGTH);
193
194		memset(iv, 0xee, enc->iv_len);
195		memset(key, 0x0, EVP_MAX_KEY_LENGTH);
196
197		/* The 'iv' is used as the iv and as a salt.  It is
198		 * NOT taken from the BytesToKey function */
199		EVP_BytesToKey(enc, EVP_md5(), iv, kstr, klen, 1, key, NULL);
200
201
202		dump_bytes("key from EVP_BytesToKey:", key, EVP_MAX_KEY_LENGTH);
203
204		if (kstr == (unsigned char *)buf) {
205			memset(buf, 0, PEM_BUFSIZE);
206		}
207
208		/* assert(strlen(objstr)+23+2*enc->iv_len+13 <= sizeof buf); */
209
210		buf[0] = '\0';
211		//PEM_proc_type(buf, PEM_TYPE_ENCRYPTED);
212		//PEM_dek_info(buf, objstr, enc->iv_len, (char *)iv);
213		/* k=strlen(buf); */
214
215		EVP_CIPHER_CTX_init(&ctx);
216		EVP_CipherInit_ex(&ctx, enc, NULL, key, iv, 1);
217
218		EVP_CipherUpdate(&ctx, data, &j, data, i);
219		printf("after EVP_CipherUpdate(): in length 'i': %d, out length 'j'%d\n", i, j);
220		dump_bytes("after EVP_CipherUpdate() data:", data, i);
221
222		EVP_CipherFinal_ex(&ctx, &(data[j]), &i);
223		printf("after EVP_CipherFinal_ex(): out length 'i': %d\n", i);
224
225		EVP_CIPHER_CTX_cleanup(&ctx);
226
227		i += j;
228
229		dump_bytes("after EVP_CIPHER_CTX_cleanup() final data:", data, i);
230		dump_bytes("2 after EVP_CIPHER_CTX_cleanup() final data:", data, data_buffer_size);
231
232		ret = 1;
233	} else {
234		ret = 1;
235		buf[0] = '\0';
236	}
237	//i = PEM_write_bio(bp, name, buf, data, i);
238	if (i <= 0) {
239		ret = 0;
240	}
241err:
242	memset(key, 0, sizeof(key));
243	memset(iv, 0, sizeof(iv));
244	memset(&ctx, 0, sizeof(ctx));
245	memset(buf, 0, PEM_BUFSIZE);
246	if (data != NULL) {
247		memset(data, 0, dsize);
248		free(data);
249	}
250
251	return (ret);
252}
253
254
255
256int
257PEM_write_bio_RSAPrivateKey(BIO *bp, RSA *x, const EVP_CIPHER *enc,
258			    unsigned char *kstr, int klen, pem_password_cb *cb, void *u)
259{
260	EVP_PKEY *k;
261	int ret;
262
263	k = EVP_PKEY_new();
264	if (!k) {
265		return (0);
266	}
267	EVP_PKEY_set1_RSA(k, x);
268
269	ret = PEM_write_bio_PrivateKey(bp, k, enc, kstr, klen, cb, u);
270	EVP_PKEY_free(k);
271
272	return (ret);
273}
274
275
276/* convert SSH v2 key in OpenSSL PEM format */
277int
278main()
279{
280	int success = 0;
281	const char *_passphrase = "abcde";
282
283	int blen, len = (int)strlen(_passphrase);
284	u_char *passphrase = (len > 0) ? (u_char *)_passphrase : NULL;
285
286#if (OPENSSL_VERSION_NUMBER < 0x00907000L)
287	const EVP_CIPHER *cipher = (len > 0) ? EVP_des_ede3_cbc() : NULL;
288#else
289	const EVP_CIPHER *cipher = (len > 0) ? EVP_aes_128_cbc() : NULL;
290#endif
291	const u_char *bptr;
292	BIO *bio;
293
294	if (len > 0 && len <= 4) {
295		error("passphrase too short: have %d bytes, need > 4", len);
296		return 0;
297	}
298	if ((bio = BIO_new(BIO_s_mem())) == NULL) {
299		error("%s: BIO_new failed", __func__);
300		return 0;
301	}
302
303#ifdef __APPLE_CRYPTO__
304	printf("Using Apple Crypto\n");
305#else
306	printf("Using OpenSSL Crypto\n");
307#endif
308
309	RSA *rsa_key_ptr = RSA_new();
310
311	rsa_key_ptr->n = BN_new();
312	rsa_key_ptr->e = BN_new();
313	rsa_key_ptr->d = BN_new();
314	rsa_key_ptr->p = BN_new();
315	rsa_key_ptr->q = BN_new();
316	rsa_key_ptr->dmp1 = BN_new();
317	rsa_key_ptr->dmq1 = BN_new();
318	rsa_key_ptr->iqmp = BN_new();
319
320	BN_set_word(rsa_key_ptr->n, 1);
321	BN_set_word(rsa_key_ptr->e, 2);
322	BN_set_word(rsa_key_ptr->d, 3);
323	BN_set_word(rsa_key_ptr->p, 4);
324	BN_set_word(rsa_key_ptr->q, 5);
325	BN_set_word(rsa_key_ptr->dmp1, 6);
326	BN_set_word(rsa_key_ptr->dmq1, 7);
327	BN_set_word(rsa_key_ptr->iqmp, 8);
328
329	success = PEM_write_bio_RSAPrivateKey(bio, rsa_key_ptr, cipher, passphrase, len, NULL, NULL);
330
331	/*
332	if (success) {
333		if ((blen = BIO_get_mem_data(bio, &bptr)) <= 0)
334			success = 0;
335		else
336			buffer_append(blob, bptr, blen);
337	}
338	BIO_free(bio);
339	 */
340	return success;
341}
342
343
344