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