-int PEM_read_bio(bp, name, header, data, len)
-BIO *bp;
-char **name;
-char **header;
-unsigned char **data;
-long *len;
- {
- EVP_ENCODE_CTX ctx;
- int end=0,i,k,bl=0,hl=0,nohead=0;
- char buf[256];
- BUF_MEM *nameB;
- BUF_MEM *headerB;
- BUF_MEM *dataB,*tmpB;
-
- nameB=BUF_MEM_new();
- headerB=BUF_MEM_new();
- dataB=BUF_MEM_new();
- if ((nameB == NULL) || (headerB == NULL) || (dataB == NULL))
- {
- PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE);
- return(0);
- }
-
- buf[254]='\0';
- for (;;)
- {
- i=BIO_gets(bp,buf,254);
-
- if (i <= 0)
- {
- PEMerr(PEM_F_PEM_READ_BIO,PEM_R_NO_START_LINE);
- goto err;
- }
-
- while ((i >= 0) && (buf[i] <= ' ')) i--;
- buf[++i]='\n'; buf[++i]='\0';
-
- if (strncmp(buf,"-----BEGIN ",11) == 0)
- {
- i=strlen(&(buf[11]));
-
- if (strncmp(&(buf[11+i-6]),"-----\n",6) != 0)
- continue;
- if (!BUF_MEM_grow(nameB,i+9))
- {
- PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE);
- goto err;
- }
- strncpy(nameB->data,&(buf[11]),(unsigned int)i-6);
- nameB->data[i-6]='\0';
- break;
- }
- }
- hl=0;
- if (!BUF_MEM_grow(headerB,256))
- { PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); goto err; }
- headerB->data[0]='\0';
- for (;;)
- {
- i=BIO_gets(bp,buf,254);
- if (i <= 0) break;
-
- while ((i >= 0) && (buf[i] <= ' ')) i--;
- buf[++i]='\n'; buf[++i]='\0';
-
- if (buf[0] == '\n') break;
- if (!BUF_MEM_grow(headerB,hl+i+9))
- { PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); goto err; }
- if (strncmp(buf,"-----END ",9) == 0)
- {
- nohead=1;
- break;
- }
- strncpy(&(headerB->data[hl]),buf,(unsigned int)i);
- headerB->data[hl+i]='\0';
- hl+=i;
- }
-
- bl=0;
- if (!BUF_MEM_grow(dataB,1024))
- { PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); goto err; }
- dataB->data[0]='\0';
- if (!nohead)
- {
- for (;;)
- {
- i=BIO_gets(bp,buf,254);
- if (i <= 0) break;
-
- while ((i >= 0) && (buf[i] <= ' ')) i--;
- buf[++i]='\n'; buf[++i]='\0';
-
- if (i != 65) end=1;
- if (strncmp(buf,"-----END ",9) == 0)
- break;
- if (i > 65) break;
- if (!BUF_MEM_grow(dataB,i+bl+9))
- {
- PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE);
- goto err;
- }
- strncpy(&(dataB->data[bl]),buf,(unsigned int)i);
- dataB->data[bl+i]='\0';
- bl+=i;
- if (end)
- {
- buf[0]='\0';
- i=BIO_gets(bp,buf,254);
- if (i <= 0) break;
-
- while ((i >= 0) && (buf[i] <= ' ')) i--;
- buf[++i]='\n'; buf[++i]='\0';
-
- break;
- }
- }
- }
- else
- {
- tmpB=headerB;
- headerB=dataB;
- dataB=tmpB;
- bl=hl;
- }
- i=strlen(nameB->data);
- if ( (strncmp(buf,"-----END ",9) != 0) ||
- (strncmp(nameB->data,&(buf[9]),(unsigned int)i) != 0) ||
- (strncmp(&(buf[9+i]),"-----\n",6) != 0))
- {
- PEMerr(PEM_F_PEM_READ_BIO,PEM_R_BAD_END_LINE);
- goto err;
- }
-
- EVP_DecodeInit(&ctx);
- i=EVP_DecodeUpdate(&ctx,
- (unsigned char *)dataB->data,&bl,
- (unsigned char *)dataB->data,bl);
- if (i < 0)
- {
- PEMerr(PEM_F_PEM_READ_BIO,PEM_R_BAD_BASE64_DECODE);
- goto err;
- }
- i=EVP_DecodeFinal(&ctx,(unsigned char *)&(dataB->data[bl]),&k);
- if (i < 0)
- {
- PEMerr(PEM_F_PEM_READ_BIO,PEM_R_BAD_BASE64_DECODE);
- goto err;
- }
- bl+=k;
-
- if (bl == 0) goto err;
- *name=nameB->data;
- *header=headerB->data;
- *data=(unsigned char *)dataB->data;
- *len=bl;
- Free(nameB);
- Free(headerB);
- Free(dataB);
- return(1);
-err:
- BUF_MEM_free(nameB);
- BUF_MEM_free(headerB);
- BUF_MEM_free(dataB);
- return(0);
- }
+int PEM_write_bio(BIO *bp, const char *name, const char *header,
+ const unsigned char *data, long len)
+{
+ int nlen, n, i, j, outl;
+ unsigned char *buf = NULL;
+ EVP_ENCODE_CTX ctx;
+ int reason = ERR_R_BUF_LIB;
+
+ EVP_EncodeInit(&ctx);
+ nlen = strlen(name);
+
+ if ((BIO_write(bp, "-----BEGIN ", 11) != 11) ||
+ (BIO_write(bp, name, nlen) != nlen) ||
+ (BIO_write(bp, "-----\n", 6) != 6))
+ goto err;
+
+ i = strlen(header);
+ if (i > 0) {
+ if ((BIO_write(bp, header, i) != i) || (BIO_write(bp, "\n", 1) != 1))
+ goto err;
+ }
+
+ buf = OPENSSL_malloc(PEM_BUFSIZE * 8);
+ if (buf == NULL) {
+ reason = ERR_R_MALLOC_FAILURE;
+ goto err;
+ }
+
+ i = j = 0;
+ while (len > 0) {
+ n = (int)((len > (PEM_BUFSIZE * 5)) ? (PEM_BUFSIZE * 5) : len);
+ EVP_EncodeUpdate(&ctx, buf, &outl, &(data[j]), n);
+ if ((outl) && (BIO_write(bp, (char *)buf, outl) != outl))
+ goto err;
+ i += outl;
+ len -= n;
+ j += n;
+ }
+ EVP_EncodeFinal(&ctx, buf, &outl);
+ if ((outl > 0) && (BIO_write(bp, (char *)buf, outl) != outl))
+ goto err;
+ OPENSSL_clear_free(buf, PEM_BUFSIZE * 8);
+ buf = NULL;
+ if ((BIO_write(bp, "-----END ", 9) != 9) ||
+ (BIO_write(bp, name, nlen) != nlen) ||
+ (BIO_write(bp, "-----\n", 6) != 6))
+ goto err;
+ return (i + outl);
+ err:
+ OPENSSL_clear_free(buf, PEM_BUFSIZE * 8);
+ PEMerr(PEM_F_PEM_WRITE_BIO, reason);
+ return (0);
+}
+
+#ifndef OPENSSL_NO_STDIO
+int PEM_read(FILE *fp, char **name, char **header, unsigned char **data,
+ long *len)
+{
+ BIO *b;
+ int ret;
+
+ if ((b = BIO_new(BIO_s_file())) == NULL) {
+ PEMerr(PEM_F_PEM_READ, ERR_R_BUF_LIB);
+ return (0);
+ }
+ BIO_set_fp(b, fp, BIO_NOCLOSE);
+ ret = PEM_read_bio(b, name, header, data, len);
+ BIO_free(b);
+ return (ret);
+}
+#endif
+
+int PEM_read_bio(BIO *bp, char **name, char **header, unsigned char **data,
+ long *len)
+{
+ EVP_ENCODE_CTX ctx;
+ int end = 0, i, k, bl = 0, hl = 0, nohead = 0;
+ char buf[256];
+ BUF_MEM *nameB;
+ BUF_MEM *headerB;
+ BUF_MEM *dataB, *tmpB;
+
+ nameB = BUF_MEM_new();
+ headerB = BUF_MEM_new();
+ dataB = BUF_MEM_new();
+ if ((nameB == NULL) || (headerB == NULL) || (dataB == NULL)) {
+ BUF_MEM_free(nameB);
+ BUF_MEM_free(headerB);
+ BUF_MEM_free(dataB);
+ PEMerr(PEM_F_PEM_READ_BIO, ERR_R_MALLOC_FAILURE);
+ return (0);
+ }
+
+ buf[254] = '\0';
+ for (;;) {
+ i = BIO_gets(bp, buf, 254);
+
+ if (i <= 0) {
+ PEMerr(PEM_F_PEM_READ_BIO, PEM_R_NO_START_LINE);
+ goto err;
+ }
+
+ while ((i >= 0) && (buf[i] <= ' '))
+ i--;
+ buf[++i] = '\n';
+ buf[++i] = '\0';
+
+ if (strncmp(buf, "-----BEGIN ", 11) == 0) {
+ i = strlen(&(buf[11]));
+
+ if (strncmp(&(buf[11 + i - 6]), "-----\n", 6) != 0)
+ continue;
+ if (!BUF_MEM_grow(nameB, i + 9)) {
+ PEMerr(PEM_F_PEM_READ_BIO, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ memcpy(nameB->data, &(buf[11]), i - 6);
+ nameB->data[i - 6] = '\0';
+ break;
+ }
+ }
+ hl = 0;
+ if (!BUF_MEM_grow(headerB, 256)) {
+ PEMerr(PEM_F_PEM_READ_BIO, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ headerB->data[0] = '\0';
+ for (;;) {
+ i = BIO_gets(bp, buf, 254);
+ if (i <= 0)
+ break;
+
+ while ((i >= 0) && (buf[i] <= ' '))
+ i--;
+ buf[++i] = '\n';
+ buf[++i] = '\0';
+
+ if (buf[0] == '\n')
+ break;
+ if (!BUF_MEM_grow(headerB, hl + i + 9)) {
+ PEMerr(PEM_F_PEM_READ_BIO, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ if (strncmp(buf, "-----END ", 9) == 0) {
+ nohead = 1;
+ break;
+ }
+ memcpy(&(headerB->data[hl]), buf, i);
+ headerB->data[hl + i] = '\0';
+ hl += i;
+ }
+
+ bl = 0;
+ if (!BUF_MEM_grow(dataB, 1024)) {
+ PEMerr(PEM_F_PEM_READ_BIO, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ dataB->data[0] = '\0';
+ if (!nohead) {
+ for (;;) {
+ i = BIO_gets(bp, buf, 254);
+ if (i <= 0)
+ break;
+
+ while ((i >= 0) && (buf[i] <= ' '))
+ i--;
+ buf[++i] = '\n';
+ buf[++i] = '\0';
+
+ if (i != 65)
+ end = 1;
+ if (strncmp(buf, "-----END ", 9) == 0)
+ break;
+ if (i > 65)
+ break;
+ if (!BUF_MEM_grow_clean(dataB, i + bl + 9)) {
+ PEMerr(PEM_F_PEM_READ_BIO, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ memcpy(&(dataB->data[bl]), buf, i);
+ dataB->data[bl + i] = '\0';
+ bl += i;
+ if (end) {
+ buf[0] = '\0';
+ i = BIO_gets(bp, buf, 254);
+ if (i <= 0)
+ break;
+
+ while ((i >= 0) && (buf[i] <= ' '))
+ i--;
+ buf[++i] = '\n';
+ buf[++i] = '\0';
+
+ break;
+ }
+ }
+ } else {
+ tmpB = headerB;
+ headerB = dataB;
+ dataB = tmpB;
+ bl = hl;
+ }
+ i = strlen(nameB->data);
+ if ((strncmp(buf, "-----END ", 9) != 0) ||
+ (strncmp(nameB->data, &(buf[9]), i) != 0) ||
+ (strncmp(&(buf[9 + i]), "-----\n", 6) != 0)) {
+ PEMerr(PEM_F_PEM_READ_BIO, PEM_R_BAD_END_LINE);
+ goto err;
+ }
+
+ EVP_DecodeInit(&ctx);
+ i = EVP_DecodeUpdate(&ctx,
+ (unsigned char *)dataB->data, &bl,
+ (unsigned char *)dataB->data, bl);
+ if (i < 0) {
+ PEMerr(PEM_F_PEM_READ_BIO, PEM_R_BAD_BASE64_DECODE);
+ goto err;
+ }
+ i = EVP_DecodeFinal(&ctx, (unsigned char *)&(dataB->data[bl]), &k);
+ if (i < 0) {
+ PEMerr(PEM_F_PEM_READ_BIO, PEM_R_BAD_BASE64_DECODE);
+ goto err;
+ }
+ bl += k;
+
+ if (bl == 0)
+ goto err;
+ *name = nameB->data;
+ *header = headerB->data;
+ *data = (unsigned char *)dataB->data;
+ *len = bl;
+ OPENSSL_free(nameB);
+ OPENSSL_free(headerB);
+ OPENSSL_free(dataB);
+ return (1);
+ err:
+ BUF_MEM_free(nameB);
+ BUF_MEM_free(headerB);
+ BUF_MEM_free(dataB);
+ return (0);
+}
+
+/*
+ * Check pem string and return prefix length. If for example the pem_str ==
+ * "RSA PRIVATE KEY" and suffix = "PRIVATE KEY" the return value is 3 for the
+ * string "RSA".
+ */
+
+int pem_check_suffix(const char *pem_str, const char *suffix)
+{
+ int pem_len = strlen(pem_str);
+ int suffix_len = strlen(suffix);
+ const char *p;
+ if (suffix_len + 1 >= pem_len)
+ return 0;
+ p = pem_str + pem_len - suffix_len;
+ if (strcmp(p, suffix))
+ return 0;
+ p--;
+ if (*p != ' ')
+ return 0;
+ return p - pem_str;
+}