static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb) { BUF_MEM *b; unsigned char *p; int i; ASN1_const_CTX c; size_t want = HEADER_SIZE; int eos = 0; size_t off = 0; size_t len = 0; b = BUF_MEM_new(); if (b == NULL) { OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); return -1; } ERR_clear_error(); for (;;) { if (want >= (len - off)) { want -= (len - off); if (len + want < len || !BUF_MEM_grow_clean(b, len + want)) { OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); goto err; } i = BIO_read(in, &(b->data[len]), want); if ((i < 0) && ((len - off) == 0)) { OPENSSL_PUT_ERROR(ASN1, ASN1_R_NOT_ENOUGH_DATA); goto err; } if (i > 0) { if (len + i < len) { OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG); goto err; } len += i; } } /* else data already loaded */ p = (unsigned char *)&(b->data[off]); c.p = p; c.inf = ASN1_get_object(&(c.p), &(c.slen), &(c.tag), &(c.xclass), len - off); if (c.inf & 0x80) { uint32_t e; e = ERR_GET_REASON(ERR_peek_error()); if (e != ASN1_R_TOO_LONG) goto err; else ERR_clear_error(); /* clear error */ } i = c.p - p; /* header length */ off += i; /* end of data */ if (c.inf & 1) { /* no data body so go round again */ eos++; if (eos < 0) { OPENSSL_PUT_ERROR(ASN1, ASN1_R_HEADER_TOO_LONG); goto err; } want = HEADER_SIZE; } else if (eos && (c.slen == 0) && (c.tag == V_ASN1_EOC)) { /* eos value, so go back and read another header */ eos--; if (eos <= 0) break; else want = HEADER_SIZE; } else { /* suck in c.slen bytes of data */ want = c.slen; if (want > (len - off)) { want -= (len - off); if (want > INT_MAX /* BIO_read takes an int length */ || len + want < len) { OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG); goto err; } if (!BUF_MEM_grow_clean(b, len + want)) { OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); goto err; } while (want > 0) { i = BIO_read(in, &(b->data[len]), want); if (i <= 0) { OPENSSL_PUT_ERROR(ASN1, ASN1_R_NOT_ENOUGH_DATA); goto err; } /* * This can't overflow because |len+want| didn't * overflow. */ len += i; want -= i; } } if (off + c.slen < off) { OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG); goto err; } off += c.slen; if (eos <= 0) { break; } else want = HEADER_SIZE; } } if (off > INT_MAX) { OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG); goto err; } *pb = b; return off; err: if (b != NULL) BUF_MEM_free(b); return -1; }
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); }
int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) { int ret=0; int i,j; BIO *btmp; BUF_MEM *buf_mem=NULL; BUF_MEM *buf=NULL; PKCS7_SIGNER_INFO *si; EVP_MD_CTX *mdc,ctx_tmp; STACK_OF(X509_ATTRIBUTE) *sk; STACK_OF(PKCS7_SIGNER_INFO) *si_sk=NULL; ASN1_OCTET_STRING *os=NULL; if (p7 == NULL) { PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_INVALID_NULL_POINTER); return 0; } if (p7->d.ptr == NULL) { PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_NO_CONTENT); return 0; } EVP_MD_CTX_init(&ctx_tmp); i=OBJ_obj2nid(p7->type); p7->state=PKCS7_S_HEADER; switch (i) { case NID_pkcs7_signedAndEnveloped: /* XXXXXXXXXXXXXXXX */ si_sk=p7->d.signed_and_enveloped->signer_info; if (!(os=M_ASN1_OCTET_STRING_new())) { PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_MALLOC_FAILURE); goto err; } p7->d.signed_and_enveloped->enc_data->enc_data=os; break; case NID_pkcs7_enveloped: /* XXXXXXXXXXXXXXXX */ if (!(os=M_ASN1_OCTET_STRING_new())) { PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_MALLOC_FAILURE); goto err; } p7->d.enveloped->enc_data->enc_data=os; break; case NID_pkcs7_signed: si_sk=p7->d.sign->signer_info; os=PKCS7_get_octet_string(p7->d.sign->contents); /* If detached data then the content is excluded */ if(PKCS7_type_is_data(p7->d.sign->contents) && p7->detached) { M_ASN1_OCTET_STRING_free(os); os = NULL; p7->d.sign->contents->d.data = NULL; } break; case NID_pkcs7_digest: os=PKCS7_get_octet_string(p7->d.digest->contents); /* If detached data then the content is excluded */ if(PKCS7_type_is_data(p7->d.digest->contents) && p7->detached) { M_ASN1_OCTET_STRING_free(os); os = NULL; p7->d.digest->contents->d.data = NULL; } break; } if (si_sk != NULL) { if ((buf=BUF_MEM_new()) == NULL) { PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_BIO_LIB); goto err; } for (i=0; i<sk_PKCS7_SIGNER_INFO_num(si_sk); i++) { si=sk_PKCS7_SIGNER_INFO_value(si_sk,i); if (si->pkey == NULL) continue; j=OBJ_obj2nid(si->digest_alg->algorithm); btmp=bio; btmp = PKCS7_find_digest(&mdc, btmp, j); if (btmp == NULL) goto err; /* We now have the EVP_MD_CTX, lets do the * signing. */ EVP_MD_CTX_copy_ex(&ctx_tmp,mdc); if (!BUF_MEM_grow_clean(buf,EVP_PKEY_size(si->pkey))) { PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_BIO_LIB); goto err; } sk=si->auth_attr; /* If there are attributes, we add the digest * attribute and only sign the attributes */ if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0)) { unsigned char md_data[EVP_MAX_MD_SIZE], *abuf=NULL; unsigned int md_len, alen; ASN1_OCTET_STRING *digest; ASN1_UTCTIME *sign_time; const EVP_MD *md_tmp; /* Add signing time if not already present */ if (!PKCS7_get_signed_attribute(si, NID_pkcs9_signingTime)) { if (!(sign_time=X509_gmtime_adj(NULL,0))) { PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_MALLOC_FAILURE); goto err; } if (!PKCS7_add_signed_attribute(si, NID_pkcs9_signingTime, V_ASN1_UTCTIME,sign_time)) { M_ASN1_UTCTIME_free(sign_time); goto err; } } /* Add digest */ md_tmp=EVP_MD_CTX_md(&ctx_tmp); EVP_DigestFinal_ex(&ctx_tmp,md_data,&md_len); if (!(digest=M_ASN1_OCTET_STRING_new())) { PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_MALLOC_FAILURE); goto err; } if (!M_ASN1_OCTET_STRING_set(digest,md_data, md_len)) { PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_MALLOC_FAILURE); M_ASN1_OCTET_STRING_free(digest); goto err; } if (!PKCS7_add_signed_attribute(si, NID_pkcs9_messageDigest, V_ASN1_OCTET_STRING,digest)) { M_ASN1_OCTET_STRING_free(digest); goto err; } /* Now sign the attributes */ EVP_SignInit_ex(&ctx_tmp,md_tmp,NULL); alen = ASN1_item_i2d((ASN1_VALUE *)sk,&abuf, ASN1_ITEM_rptr(PKCS7_ATTR_SIGN)); if(!abuf) goto err; EVP_SignUpdate(&ctx_tmp,abuf,alen); OPENSSL_free(abuf); } #ifndef OPENSSL_NO_DSA if (si->pkey->type == EVP_PKEY_DSA) ctx_tmp.digest=EVP_dss1(); #endif #ifndef OPENSSL_NO_ECDSA if (si->pkey->type == EVP_PKEY_EC) ctx_tmp.digest=EVP_ecdsa(); #endif if (!EVP_SignFinal(&ctx_tmp,(unsigned char *)buf->data, (unsigned int *)&buf->length,si->pkey)) { PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_EVP_LIB); goto err; } if (!ASN1_STRING_set(si->enc_digest, (unsigned char *)buf->data,buf->length)) { PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_ASN1_LIB); goto err; } } } else if (i == NID_pkcs7_digest) { unsigned char md_data[EVP_MAX_MD_SIZE]; unsigned int md_len; if (!PKCS7_find_digest(&mdc, bio, OBJ_obj2nid(p7->d.digest->md->algorithm))) goto err; EVP_DigestFinal_ex(mdc,md_data,&md_len); M_ASN1_OCTET_STRING_set(p7->d.digest->digest, md_data, md_len); } if (!PKCS7_is_detached(p7)) { /* * NOTE(emilia): I think we only reach os == NULL here because detached * digested data support is broken. */ if (os == NULL) goto err; btmp=BIO_find_type(bio,BIO_TYPE_MEM); if (btmp == NULL) { PKCS7err(PKCS7_F_PKCS7_DATAFINAL,PKCS7_R_UNABLE_TO_FIND_MEM_BIO); goto err; } BIO_get_mem_ptr(btmp,&buf_mem); /* Mark the BIO read only then we can use its copy of the data * instead of making an extra copy. */ BIO_set_flags(btmp, BIO_FLAGS_MEM_RDONLY); BIO_set_mem_eof_return(btmp, 0); os->data = (unsigned char *)buf_mem->data; os->length = buf_mem->length; #if 0 M_ASN1_OCTET_STRING_set(os, (unsigned char *)buf_mem->data,buf_mem->length); #endif } ret=1; err: EVP_MD_CTX_cleanup(&ctx_tmp); if (buf != NULL) BUF_MEM_free(buf); return(ret); }