-int PEM_ASN1_write_bio(int (*i2d)(), const char *name, BIO *bp, char *x,
- const EVP_CIPHER *enc, unsigned char *kstr, int klen,
- int (*callback)())
- {
- EVP_CIPHER_CTX ctx;
- int dsize=0,i,j,ret=0;
- unsigned char *p,*data=NULL;
- const char *objstr=NULL;
-#define PEM_BUFSIZE 1024
- char buf[PEM_BUFSIZE];
- unsigned char key[EVP_MAX_KEY_LENGTH];
- unsigned char iv[EVP_MAX_IV_LENGTH];
-
- if (enc != NULL)
- {
- objstr=OBJ_nid2sn(EVP_CIPHER_nid(enc));
- if (objstr == NULL)
- {
- PEMerr(PEM_F_PEM_ASN1_WRITE_BIO,PEM_R_UNSUPPORTED_CIPHER);
- goto err;
- }
- }
-
- if ((dsize=i2d(x,NULL)) < 0)
- {
- PEMerr(PEM_F_PEM_ASN1_WRITE_BIO,ERR_R_MALLOC_FAILURE);
- dsize=0;
- goto err;
- }
- /* dzise + 8 bytes are needed */
- data=(unsigned char *)Malloc((unsigned int)dsize+20);
- if (data == NULL)
- {
- PEMerr(PEM_F_PEM_ASN1_WRITE_BIO,ERR_R_MALLOC_FAILURE);
- goto err;
- }
- p=data;
- i=i2d(x,&p);
-
- if (enc != NULL)
- {
- if (kstr == NULL)
- {
- if (callback == NULL)
- klen=def_callback(buf,PEM_BUFSIZE,1);
- else
- klen=(*callback)(buf,PEM_BUFSIZE,1);
- if (klen <= 0)
- {
- PEMerr(PEM_F_PEM_ASN1_WRITE_BIO,PEM_R_READ_KEY);
- goto err;
- }
- kstr=(unsigned char *)buf;
- }
- RAND_seed(data,i);/* put in the RSA key. */
- RAND_bytes(iv,8); /* Generate a salt */
- /* The 'iv' is used as the iv and as a salt. It is
- * NOT taken from the BytesToKey function */
- EVP_BytesToKey(enc,EVP_md5(),iv,kstr,klen,1,key,NULL);
-
- if (kstr == (unsigned char *)buf) memset(buf,0,PEM_BUFSIZE);
-
- buf[0]='\0';
- PEM_proc_type(buf,PEM_TYPE_ENCRYPTED);
- PEM_dek_info(buf,objstr,8,(char *)iv);
- /* k=strlen(buf); */
-
- EVP_EncryptInit(&ctx,enc,key,iv);
- EVP_EncryptUpdate(&ctx,data,&j,data,i);
- EVP_EncryptFinal(&ctx,&(data[j]),&i);
- i+=j;
- ret=1;
- }
- else
- {
- ret=1;
- buf[0]='\0';
- }
- i=PEM_write_bio(bp,name,buf,data,i);
- if (i <= 0) ret=0;
-err:
- memset(key,0,sizeof(key));
- memset(iv,0,sizeof(iv));
- memset((char *)&ctx,0,sizeof(ctx));
- memset(buf,0,PEM_BUFSIZE);
- memset(data,0,(unsigned int)dsize);
- Free(data);
- return(ret);
- }
+ return 0;
+}
+
+int PEM_bytes_read_bio(unsigned char **pdata, long *plen, char **pnm,
+ const char *name, BIO *bp, pem_password_cb *cb,
+ void *u)
+{
+ EVP_CIPHER_INFO cipher;
+ char *nm = NULL, *header = NULL;
+ unsigned char *data = NULL;
+ long len;
+ int ret = 0;
+
+ for (;;) {
+ if (!PEM_read_bio(bp, &nm, &header, &data, &len)) {
+ if (ERR_GET_REASON(ERR_peek_error()) == PEM_R_NO_START_LINE)
+ ERR_add_error_data(2, "Expecting: ", name);
+ return 0;
+ }
+ if (check_pem(nm, name))
+ break;
+ OPENSSL_free(nm);
+ OPENSSL_free(header);
+ OPENSSL_free(data);
+ }
+ if (!PEM_get_EVP_CIPHER_INFO(header, &cipher))
+ goto err;
+ if (!PEM_do_header(&cipher, data, &len, cb, u))
+ goto err;
+
+ *pdata = data;
+ *plen = len;
+
+ if (pnm)
+ *pnm = nm;
+
+ ret = 1;
+
+ err:
+ if (!ret || !pnm)
+ OPENSSL_free(nm);
+ OPENSSL_free(header);
+ if (!ret)
+ OPENSSL_free(data);
+ return ret;
+}
+
+#ifndef OPENSSL_NO_STDIO
+int PEM_ASN1_write(i2d_of_void *i2d, const char *name, FILE *fp,
+ void *x, const EVP_CIPHER *enc, unsigned char *kstr,
+ int klen, pem_password_cb *callback, void *u)
+{
+ BIO *b;
+ int ret;
+
+ if ((b = BIO_new(BIO_s_file())) == NULL) {
+ PEMerr(PEM_F_PEM_ASN1_WRITE, ERR_R_BUF_LIB);
+ return (0);
+ }
+ BIO_set_fp(b, fp, BIO_NOCLOSE);
+ ret = PEM_ASN1_write_bio(i2d, name, b, x, enc, kstr, klen, callback, u);
+ BIO_free(b);
+ return (ret);
+}
+#endif
+
+int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp,
+ void *x, const EVP_CIPHER *enc, unsigned char *kstr,
+ int klen, pem_password_cb *callback, void *u)
+{
+ EVP_CIPHER_CTX ctx;
+ int dsize = 0, i = 0, j = 0, ret = 0;
+ unsigned char *p, *data = NULL;
+ const char *objstr = NULL;
+ char buf[PEM_BUFSIZE];
+ unsigned char key[EVP_MAX_KEY_LENGTH];
+ unsigned char iv[EVP_MAX_IV_LENGTH];
+
+ if (enc != NULL) {
+ objstr = OBJ_nid2sn(EVP_CIPHER_nid(enc));
+ if (objstr == NULL) {
+ PEMerr(PEM_F_PEM_ASN1_WRITE_BIO, PEM_R_UNSUPPORTED_CIPHER);
+ goto err;
+ }
+ }
+
+ if ((dsize = i2d(x, NULL)) < 0) {
+ PEMerr(PEM_F_PEM_ASN1_WRITE_BIO, ERR_R_ASN1_LIB);
+ dsize = 0;
+ goto err;
+ }
+ /* dzise + 8 bytes are needed */
+ /* actually it needs the cipher block size extra... */
+ data = OPENSSL_malloc((unsigned int)dsize + 20);
+ if (data == NULL) {
+ PEMerr(PEM_F_PEM_ASN1_WRITE_BIO, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ p = data;
+ i = i2d(x, &p);
+
+ if (enc != NULL) {
+ if (kstr == NULL) {
+ if (callback == NULL)
+ klen = PEM_def_callback(buf, PEM_BUFSIZE, 1, u);
+ else
+ klen = (*callback) (buf, PEM_BUFSIZE, 1, u);
+ if (klen <= 0) {
+ PEMerr(PEM_F_PEM_ASN1_WRITE_BIO, PEM_R_READ_KEY);
+ goto err;
+ }
+#ifdef CHARSET_EBCDIC
+ /* Convert the pass phrase from EBCDIC */
+ ebcdic2ascii(buf, buf, klen);
+#endif
+ kstr = (unsigned char *)buf;
+ }
+ RAND_add(data, i, 0); /* put in the RSA key. */
+ OPENSSL_assert(enc->iv_len <= (int)sizeof(iv));
+ if (RAND_bytes(iv, enc->iv_len) <= 0) /* Generate a salt */
+ goto err;
+ /*
+ * The 'iv' is used as the iv and as a salt. It is NOT taken from
+ * the BytesToKey function
+ */
+ if (!EVP_BytesToKey(enc, EVP_md5(), iv, kstr, klen, 1, key, NULL))
+ goto err;
+
+ if (kstr == (unsigned char *)buf)
+ OPENSSL_cleanse(buf, PEM_BUFSIZE);
+
+ OPENSSL_assert(strlen(objstr) + 23 + 2 * enc->iv_len + 13 <=
+ sizeof buf);
+
+ buf[0] = '\0';
+ PEM_proc_type(buf, PEM_TYPE_ENCRYPTED);
+ PEM_dek_info(buf, objstr, enc->iv_len, (char *)iv);
+ /* k=strlen(buf); */
+
+ EVP_CIPHER_CTX_init(&ctx);
+ ret = 1;
+ if (!EVP_EncryptInit_ex(&ctx, enc, NULL, key, iv)
+ || !EVP_EncryptUpdate(&ctx, data, &j, data, i)
+ || !EVP_EncryptFinal_ex(&ctx, &(data[j]), &i))
+ ret = 0;
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ if (ret == 0)
+ goto err;
+ i += j;
+ } else {
+ ret = 1;
+ buf[0] = '\0';
+ }
+ i = PEM_write_bio(bp, name, buf, data, i);
+ if (i <= 0)
+ ret = 0;
+ err:
+ OPENSSL_cleanse(key, sizeof(key));
+ OPENSSL_cleanse(iv, sizeof(iv));
+ OPENSSL_cleanse((char *)&ctx, sizeof(ctx));
+ OPENSSL_cleanse(buf, PEM_BUFSIZE);
+ OPENSSL_clear_free(data, (unsigned int)dsize);
+ return (ret);
+}