BIGNUM * OpenSSLCryptoBase64::b642BN(char * b64in, unsigned int len) { if (len > 1024) return NULL; int bufLen; unsigned char buf[1024]; EVP_ENCODE_CTX m_dctx; EVP_DecodeInit(&m_dctx); int rc = EVP_DecodeUpdate(&m_dctx, buf, &bufLen, (unsigned char *) b64in, len); if (rc < 0) { throw XSECCryptoException(XSECCryptoException::Base64Error, "OpenSSL:Base64 - Error during Base64 Decode of BIGNUMS"); } int finalLen; EVP_DecodeFinal(&m_dctx, &buf[bufLen], &finalLen); bufLen += finalLen; // Now translate to a bignum return BN_dup(BN_bin2bn(buf, bufLen, NULL)); }
int _ldapfull_base64_decode( const char *src, char **ret, int *rlen ) { unsigned int rc, i, tlen = 0; char *text; EVP_ENCODE_CTX EVP_ctx; text = (char *)malloc(((strlen(src)+3)/4 * 3) + 1); if (text == NULL) { return 0; } EVP_DecodeInit(&EVP_ctx); rc = EVP_DecodeUpdate(&EVP_ctx, text, &i, (char *)src, strlen(src)); if (rc < 0) { free(text); return 0; } tlen+=i; EVP_DecodeFinal(&EVP_ctx, text, &i); *ret = text; if (rlen != NULL) { *rlen = tlen; } return 1; }
int main(void) { int i, len, total = 0, total2 = 0, ret; EVP_ENCODE_CTX ctx1, ctx2; unsigned char f[60]; unsigned char t[80 + 1]; for(i = 0; i < 60; i++) { memset(&f[i], i, 1); } EVP_EncodeInit(&ctx1); EVP_EncodeUpdate(&ctx1, t, &len, f, 60); total += len; printf("total = %d\n", total); // printf("%s\n", t); EVP_EncodeFinal(&ctx1, t + total, &len); total += len; printf("%total = %d\n", total); printf("%s\n", t); EVP_DecodeInit(&ctx2); ret = EVP_DecodeUpdate(&ctx2, f, &len, t, total); total2 += len; ret = EVP_DecodeFinal(&ctx2, f, &len); total2 += len; for(i = 0; i < total2; i++) { printf("%02x\t", f[i]); } printf("\n"); return 0; }
int32_t cm_base_64_decode(unsigned char *pIn, int32_t iInlen,unsigned char *pOut, int32_t *pOutlen) { EVP_ENCODE_CTX ctx; EVP_DecodeInit(&ctx); if(EVP_DecodeUpdate(&ctx,pOut,pOutlen,pIn,iInlen)<0) return OF_FAILURE; if(EVP_DecodeFinal(&ctx,pOut,pOutlen)<0) return OF_FAILURE; return OF_SUCCESS; }
/*********************** Decode ************************/ int mite_base64_2_string(char *base64,int inlen,char **ppout) { EVP_ENCODE_CTX dctx; EVP_DecodeInit(&dctx); int outlen = 0; int total = 0; int ret = 0; char *out = malloc(inlen); ret = EVP_DecodeUpdate(&dctx,out,&outlen,base64,inlen); if(ret < 0) { printf("EVP_DecodeUpdate err!\n"); return -1; } total+=outlen; ret = EVP_DecodeFinal(&dctx,out,&outlen); total += outlen; *ppout=out; return total; }
void openssl_evp_encode() { FILE *fin, *fout; int inLen, outLen; EVP_ENCODE_CTX ctx; unsigned char ins[MAX1_LEN], outs[MAX2_LEN]; fin = fopen("/tmp/test.dat", "rb"); fout = fopen("/tmp/test.txt", "w"); memset(ins, 0, sizeof(ins)); memset(outs, 0, sizeof(outs)); printf("\nEVP_Encode(/tmp/test.dat) = "); EVP_EncodeInit(&ctx); while ((inLen = fread(ins, 1, MAX1_LEN, fin)) > 0) { EVP_EncodeUpdate(&ctx, outs, &outLen, ins, inLen); fwrite(outs, 1, outLen, fout); printf("%s", outs); } EVP_EncodeFinal(&ctx, outs, &outLen); fwrite(outs, 1, outLen, fout); printf("%s", outs); fclose(fin); fclose(fout); fin = fopen("/tmp/test.txt", "r"); fout = fopen("/tmp/test-1.dat", "wb"); memset(ins, 0, sizeof(ins)); memset(outs, 0, sizeof(outs)); printf("\nEVP_Decode(/tmp/test.txt) = "); EVP_DecodeInit(&ctx); while ((inLen = fread(ins, 1, MAX1_LEN, fin)) > 0) { EVP_DecodeUpdate(&ctx, outs, &outLen, ins, inLen); fwrite(outs, 1, outLen, fout); printf("%s", outs); } EVP_DecodeFinal(&ctx, outs, &outLen); fwrite(outs, 1, outLen, fout); printf("%s\n", outs); fclose(fin); fclose(fout); }
/* {{{ php_crypto_base64_decode_update */ static inline int php_crypto_base64_decode_update( EVP_ENCODE_CTX *ctx, char *out, int *outl, const char *in, phpc_str_size_t in_len TSRMLS_DC) { int inl, rc; /* check string length overflow */ if (php_crypto_str_size_to_int(in_len, &inl) == FAILURE) { php_crypto_error(PHP_CRYPTO_ERROR_ARGS(Base64, INPUT_DATA_LENGTH_HIGH)); return FAILURE; } rc = EVP_DecodeUpdate(ctx, (unsigned char *) out, outl, (const unsigned char *) in, inl); if (rc < 0) { php_crypto_error(PHP_CRYPTO_ERROR_ARGS(Base64, DECODE_UPDATE_FAILED)); return FAILURE; } return SUCCESS; }
unsigned int OpenSSLCryptoBase64::decode(unsigned char * inData, unsigned int inLength, unsigned char * outData, unsigned int outLength) { int rc; int outLen; if (outLength < inLength) { throw XSECCryptoException(XSECCryptoException::MemoryError, "OpenSSL:Base64 - Output buffer not big enough for Base64 decode"); } rc = EVP_DecodeUpdate(&m_dctx, outData, &outLen, inData, inLength); if (rc < 0) { throw XSECCryptoException(XSECCryptoException::Base64Error, "OpenSSL:Base64 - Error during Base64 Decode"); } if (outLen > (int) outLength) { throw XSECCryptoException(XSECCryptoException::MemoryError, "OpenSSL:Base64 - Output buffer not big enough for Base64 decode and overflowed"); } return outLen; }
static void mime_get(byte_string_t bs, FILE *infp) { char line[crypt_buf_size]; int l, l2; EVP_ENCODE_CTX mime; byte_string_init(bs, 1024); EVP_DecodeInit(&mime); l = 0; for (;;) { fgets(line, crypt_buf_size, infp); if (feof(infp)) break; //break on blank line = "\n" or "\r\n" if (strlen(line) <= 2) break; EVP_DecodeUpdate(&mime, &bs->data[l], &l2, (unsigned char *) line, strlen(line)); l += l2; if (bs->len - l < crypt_buf_size) { byte_string_reinit(bs, bs->len * 2); } } EVP_DecodeFinal(&mime, &bs->data[l], &l2); byte_string_reinit(bs, l + l2); }
/** * Read in PEM-formatted data from the given BIO. * * By nature of the PEM format, all content must be printable ASCII (except * for line endings). Other characters are malformed input and will be rejected. */ int PEM_read_bio_ex(BIO *bp, char **name_out, char **header, unsigned char **data, long *len_out, unsigned int flags) { EVP_ENCODE_CTX *ctx = EVP_ENCODE_CTX_new(); const BIO_METHOD *bmeth; BIO *headerB = NULL, *dataB = NULL; char *name = NULL; int len, taillen, headerlen, ret = 0; BUF_MEM * buf_mem; if (ctx == NULL) { PEMerr(PEM_F_PEM_READ_BIO_EX, ERR_R_MALLOC_FAILURE); return 0; } *len_out = 0; *name_out = *header = NULL; *data = NULL; if ((flags & PEM_FLAG_EAY_COMPATIBLE) && (flags & PEM_FLAG_ONLY_B64)) { /* These two are mutually incompatible; bail out. */ PEMerr(PEM_F_PEM_READ_BIO_EX, ERR_R_PASSED_INVALID_ARGUMENT); goto end; } bmeth = (flags & PEM_FLAG_SECURE) ? BIO_s_secmem() : BIO_s_mem(); headerB = BIO_new(bmeth); dataB = BIO_new(bmeth); if (headerB == NULL || dataB == NULL) { PEMerr(PEM_F_PEM_READ_BIO_EX, ERR_R_MALLOC_FAILURE); goto end; } if (!get_name(bp, &name, flags)) goto end; if (!get_header_and_data(bp, &headerB, &dataB, name, flags)) goto end; EVP_DecodeInit(ctx); BIO_get_mem_ptr(dataB, &buf_mem); len = buf_mem->length; if (EVP_DecodeUpdate(ctx, (unsigned char*)buf_mem->data, &len, (unsigned char*)buf_mem->data, len) < 0 || EVP_DecodeFinal(ctx, (unsigned char*)&(buf_mem->data[len]), &taillen) < 0) { PEMerr(PEM_F_PEM_READ_BIO_EX, PEM_R_BAD_BASE64_DECODE); goto end; } len += taillen; buf_mem->length = len; /* There was no data in the PEM file; avoid malloc(0). */ if (len == 0) goto end; headerlen = BIO_get_mem_data(headerB, NULL); *header = pem_malloc(headerlen + 1, flags); *data = pem_malloc(len, flags); if (*header == NULL || *data == NULL) { pem_free(*header, flags, 0); pem_free(*data, flags, 0); goto end; } BIO_read(headerB, *header, headerlen); (*header)[headerlen] = '\0'; BIO_read(dataB, *data, len); *len_out = len; *name_out = name; name = NULL; ret = 1; end: EVP_ENCODE_CTX_free(ctx); pem_free(name, flags, 0); BIO_free(headerB); BIO_free(dataB); return ret; }
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); }
(unsigned char *)&(ctx->tmp[jj]),i-jj); ctx->tmp_len=i-jj; } ctx->buf_len=0; if (z > 0) { ctx->buf_len=z; i=1; } else i=z; } else { i=EVP_DecodeUpdate(&(ctx->base64), (unsigned char *)ctx->buf,&ctx->buf_len, (unsigned char *)ctx->tmp,i); ctx->tmp_len = 0; } ctx->buf_off=0; if (i < 0) { ret_code=0; ctx->buf_len=0; break; } if (ctx->buf_len <= outl) i=ctx->buf_len; else i=outl;
static int b64_read(BIO *b, char *out, int outl) { int ret=0,i,ii,j,k,x,n,num,ret_code=0; BIO_B64_CTX *ctx; unsigned char *p,*q; if (out == NULL) return(0); ctx=(BIO_B64_CTX *)b->ptr; if ((ctx == NULL) || (b->next_bio == NULL)) return(0); if (ctx->encode != B64_DECODE) { ctx->encode=B64_DECODE; ctx->buf_len=0; ctx->buf_off=0; ctx->tmp_len=0; EVP_DecodeInit(&(ctx->base64)); } /* First check if there are bytes decoded/encoded */ if (ctx->buf_len > 0) { i=ctx->buf_len-ctx->buf_off; if (i > outl) i=outl; OPENSSL_assert(ctx->buf_off+i < (int)sizeof(ctx->buf)); memcpy(out,&(ctx->buf[ctx->buf_off]),i); ret=i; out+=i; outl-=i; ctx->buf_off+=i; if (ctx->buf_len == ctx->buf_off) { ctx->buf_len=0; ctx->buf_off=0; } } /* At this point, we have room of outl bytes and an empty * buffer, so we should read in some more. */ ret_code=0; while (outl > 0) { if (ctx->cont <= 0) break; i=BIO_read(b->next_bio,&(ctx->tmp[ctx->tmp_len]), B64_BLOCK_SIZE-ctx->tmp_len); if (i <= 0) { ret_code=i; /* Should be continue next time we are called? */ if (!BIO_should_retry(b->next_bio)) { ctx->cont=i; /* If buffer empty break */ if(ctx->tmp_len == 0) break; /* Fall through and process what we have */ else i = 0; } /* else we retry and add more data to buffer */ else break; } i+=ctx->tmp_len; ctx->tmp_len = i; /* We need to scan, a line at a time until we * have a valid line if we are starting. */ if (ctx->start && (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL)) { /* ctx->start=1; */ ctx->tmp_len=0; } else if (ctx->start) { q=p=(unsigned char *)ctx->tmp; for (j=0; j<i; j++) { if (*(q++) != '\n') continue; /* due to a previous very long line, * we need to keep on scanning for a '\n' * before we even start looking for * base64 encoded stuff. */ if (ctx->tmp_nl) { p=q; ctx->tmp_nl=0; continue; } k=EVP_DecodeUpdate(&(ctx->base64), (unsigned char *)ctx->buf, &num,p,q-p); if ((k <= 0) && (num == 0) && (ctx->start)) EVP_DecodeInit(&ctx->base64); else { if (p != (unsigned char *) &(ctx->tmp[0])) { i-=(p- (unsigned char *) &(ctx->tmp[0])); for (x=0; x < i; x++) ctx->tmp[x]=p[x]; } EVP_DecodeInit(&ctx->base64); ctx->start=0; break; } p=q; } /* we fell off the end without starting */ if (j == i) { /* Is this is one long chunk?, if so, keep on * reading until a new line. */ if (p == (unsigned char *)&(ctx->tmp[0])) { /* Check buffer full */ if (i == B64_BLOCK_SIZE) { ctx->tmp_nl=1; ctx->tmp_len=0; } } else if (p != q) /* finished on a '\n' */ { n=q-p; for (ii=0; ii<n; ii++) ctx->tmp[ii]=p[ii]; ctx->tmp_len=n; } /* else finished on a '\n' */ continue; } else ctx->tmp_len=0; } /* If buffer isn't full and we can retry then * restart to read in more data. */ else if ((i < B64_BLOCK_SIZE) && (ctx->cont > 0)) continue; if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL) { int z,jj; jj=(i>>2)<<2; z=EVP_DecodeBlock((unsigned char *)ctx->buf, (unsigned char *)ctx->tmp,jj); if (jj > 2) { if (ctx->tmp[jj-1] == '=') { z--; if (ctx->tmp[jj-2] == '=') z--; } } /* z is now number of output bytes and jj is the * number consumed */ if (jj != i) { memcpy((unsigned char *)ctx->tmp, (unsigned char *)&(ctx->tmp[jj]),i-jj); ctx->tmp_len=i-jj; } ctx->buf_len=0; if (z > 0) { ctx->buf_len=z; i=1; } else i=z; } else {
bool OpenSSLCryptoKeyDSA::verifyBase64Signature(unsigned char * hashBuf, unsigned int hashLen, char * base64Signature, unsigned int sigLen) { // Use the currently loaded key to validate the Base64 encoded signature if (mp_dsaKey == NULL) { throw XSECCryptoException(XSECCryptoException::DSAError, "OpenSSL:DSA - Attempt to validate signature with empty key"); } unsigned char sigVal[512]; int sigValLen; int err; /* BIO * b64 = BIO_new(BIO_f_base64()); BIO * bmem = BIO_new(BIO_s_mem()); BIO_set_mem_eof_return(bmem, 0); b64 = BIO_push(b64, bmem); // Translate signature from Base64 BIO_write(bmem, base64Signature, sigLen); sigValLen = BIO_read(b64, sigVal, 512); */ EVP_ENCODE_CTX m_dctx; int rc; EVP_DecodeInit(&m_dctx); rc = EVP_DecodeUpdate(&m_dctx, sigVal, &sigValLen, (unsigned char *) base64Signature, sigLen); if (rc < 0) { throw XSECCryptoException(XSECCryptoException::DSAError, "OpenSSL:DSA - Error during Base64 Decode"); } int t = 0; EVP_DecodeFinal(&m_dctx, &sigVal[sigValLen], &t); sigValLen += t; if (sigValLen != 40) { throw XSECCryptoException(XSECCryptoException::DSAError, "OpenSSL:DSA - Signature Length incorrect"); } // Translate to BNs and thence to DSA_SIG BIGNUM * R = BN_bin2bn(sigVal, 20, NULL); BIGNUM * S = BN_bin2bn(&sigVal[20], 20, NULL); DSA_SIG * dsa_sig = DSA_SIG_new(); dsa_sig->r = BN_dup(R); dsa_sig->s = BN_dup(S); unsigned char sigValTranslatedBuf[256]; unsigned char * sigValTranslated = sigValTranslatedBuf; int sigValTranslatedLen; sigValTranslatedLen = i2d_DSA_SIG(dsa_sig, &sigValTranslated); // Now we have a signature and a key - lets check err = DSA_do_verify(hashBuf, hashLen, dsa_sig, mp_dsaKey); DSA_SIG_free(dsa_sig); if (err < 0) { throw XSECCryptoException(XSECCryptoException::DSAError, "OpenSSL:DSA - Error validating signature"); } return (err == 1); }
/* * Convert a base64 string into raw byte array representation. * Returns the length of the decoded data, or -1 on error. */ static int t_fromb64(unsigned char *a, size_t alen, const char *src) { EVP_ENCODE_CTX *ctx; int outl = 0, outl2 = 0; size_t size, padsize; const unsigned char *pad = (const unsigned char *)"00"; while (*src == ' ' || *src == '\t' || *src == '\n') ++src; size = strlen(src); padsize = 4 - (size & 3); padsize &= 3; /* Four bytes in src become three bytes output. */ if (size > INT_MAX || ((size + padsize) / 4) * 3 > alen) return -1; ctx = EVP_ENCODE_CTX_new(); if (ctx == NULL) return -1; /* * This should never occur because 1 byte of data always requires 2 bytes of * encoding, i.e. * 0 bytes unencoded = 0 bytes encoded * 1 byte unencoded = 2 bytes encoded * 2 bytes unencoded = 3 bytes encoded * 3 bytes unencoded = 4 bytes encoded * 4 bytes unencoded = 6 bytes encoded * etc */ if (padsize == 3) { outl = -1; goto err; } /* Valid padsize values are now 0, 1 or 2 */ EVP_DecodeInit(ctx); evp_encode_ctx_set_flags(ctx, EVP_ENCODE_CTX_USE_SRP_ALPHABET); /* Add any encoded padding that is required */ if (padsize != 0 && EVP_DecodeUpdate(ctx, a, &outl, pad, padsize) < 0) { outl = -1; goto err; } if (EVP_DecodeUpdate(ctx, a, &outl2, (const unsigned char *)src, size) < 0) { outl = -1; goto err; } outl += outl2; EVP_DecodeFinal(ctx, a + outl, &outl2); outl += outl2; /* Strip off the leading padding */ if (padsize != 0) { if ((int)padsize >= outl) { outl = -1; goto err; } /* * If we added 1 byte of padding prior to encoding then we have 2 bytes * of "real" data which gets spread across 4 encoded bytes like this: * (6 bits pad)(2 bits pad | 4 bits data)(6 bits data)(6 bits data) * So 1 byte of pre-encoding padding results in 1 full byte of encoded * padding. * If we added 2 bytes of padding prior to encoding this gets encoded * as: * (6 bits pad)(6 bits pad)(4 bits pad | 2 bits data)(6 bits data) * So 2 bytes of pre-encoding padding results in 2 full bytes of encoded * padding, i.e. we have to strip the same number of bytes of padding * from the encoded data as we added to the pre-encoded data. */ memmove(a, a + padsize, outl - padsize); outl -= padsize; } err: EVP_ENCODE_CTX_free(ctx); return outl; }
static int b64_read(BIO *b, char *out, int outl) { int ret = 0, i, ii, j, k, x, n, num, ret_code = 0; BIO_B64_CTX *ctx; unsigned char *p, *q; BIO *next; if (out == NULL) return 0; ctx = (BIO_B64_CTX *)BIO_get_data(b); next = BIO_next(b); if ((ctx == NULL) || (next == NULL)) return 0; BIO_clear_retry_flags(b); if (ctx->encode != B64_DECODE) { ctx->encode = B64_DECODE; ctx->buf_len = 0; ctx->buf_off = 0; ctx->tmp_len = 0; EVP_DecodeInit(ctx->base64); } /* First check if there are bytes decoded/encoded */ if (ctx->buf_len > 0) { OPENSSL_assert(ctx->buf_len >= ctx->buf_off); i = ctx->buf_len - ctx->buf_off; if (i > outl) i = outl; OPENSSL_assert(ctx->buf_off + i < (int)sizeof(ctx->buf)); memcpy(out, &(ctx->buf[ctx->buf_off]), i); ret = i; out += i; outl -= i; ctx->buf_off += i; if (ctx->buf_len == ctx->buf_off) { ctx->buf_len = 0; ctx->buf_off = 0; } } /* * At this point, we have room of outl bytes and an empty buffer, so we * should read in some more. */ ret_code = 0; while (outl > 0) { if (ctx->cont <= 0) break; i = BIO_read(next, &(ctx->tmp[ctx->tmp_len]), B64_BLOCK_SIZE - ctx->tmp_len); if (i <= 0) { ret_code = i; /* Should we continue next time we are called? */ if (!BIO_should_retry(next)) { ctx->cont = i; /* If buffer empty break */ if (ctx->tmp_len == 0) break; /* Fall through and process what we have */ else i = 0; } /* else we retry and add more data to buffer */ else break; } i += ctx->tmp_len; ctx->tmp_len = i; /* * We need to scan, a line at a time until we have a valid line if we * are starting. */ if (ctx->start && (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL)) { /* ctx->start=1; */ ctx->tmp_len = 0; } else if (ctx->start) { q = p = (unsigned char *)ctx->tmp; num = 0; for (j = 0; j < i; j++) { if (*(q++) != '\n') continue; /* * due to a previous very long line, we need to keep on * scanning for a '\n' before we even start looking for * base64 encoded stuff. */ if (ctx->tmp_nl) { p = q; ctx->tmp_nl = 0; continue; } k = EVP_DecodeUpdate(ctx->base64, (unsigned char *)ctx->buf, &num, p, q - p); if ((k <= 0) && (num == 0) && (ctx->start)) EVP_DecodeInit(ctx->base64); else { if (p != (unsigned char *) &(ctx->tmp[0])) { i -= (p - (unsigned char *) &(ctx->tmp[0])); for (x = 0; x < i; x++) ctx->tmp[x] = p[x]; } EVP_DecodeInit(ctx->base64); ctx->start = 0; break; } p = q; } /* we fell off the end without starting */ if ((j == i) && (num == 0)) { /* * Is this is one long chunk?, if so, keep on reading until a * new line. */ if (p == (unsigned char *)&(ctx->tmp[0])) { /* Check buffer full */ if (i == B64_BLOCK_SIZE) { ctx->tmp_nl = 1; ctx->tmp_len = 0; } } else if (p != q) { /* finished on a '\n' */ n = q - p; for (ii = 0; ii < n; ii++) ctx->tmp[ii] = p[ii]; ctx->tmp_len = n; } /* else finished on a '\n' */ continue; } else { ctx->tmp_len = 0; } } else if ((i < B64_BLOCK_SIZE) && (ctx->cont > 0)) { /* * If buffer isn't full and we can retry then restart to read in * more data. */ continue; } if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL) { int z, jj; jj = i & ~3; /* process per 4 */ z = EVP_DecodeBlock((unsigned char *)ctx->buf, (unsigned char *)ctx->tmp, jj); if (jj > 2) { if (ctx->tmp[jj - 1] == '=') { z--; if (ctx->tmp[jj - 2] == '=') z--; } } /* * z is now number of output bytes and jj is the number consumed */ if (jj != i) { memmove(ctx->tmp, &ctx->tmp[jj], i - jj); ctx->tmp_len = i - jj; } ctx->buf_len = 0; if (z > 0) { ctx->buf_len = z; } i = z; } else { i = EVP_DecodeUpdate(ctx->base64, (unsigned char *)ctx->buf, &ctx->buf_len, (unsigned char *)ctx->tmp, i); ctx->tmp_len = 0; } /* * If eof or an error was signalled, then the condition * 'ctx->cont <= 0' will prevent b64_read() from reading * more data on subsequent calls. This assignment was * deleted accidentally in commit 5562cfaca4f3. */ ctx->cont = i; ctx->buf_off = 0; if (i < 0) { ret_code = 0; ctx->buf_len = 0; break; } if (ctx->buf_len <= outl) i = ctx->buf_len; else i = outl; memcpy(out, ctx->buf, i); ret += i; ctx->buf_off = i; if (ctx->buf_off == ctx->buf_len) { ctx->buf_len = 0; ctx->buf_off = 0; } outl -= i; out += i; } /* BIO_clear_retry_flags(b); */ BIO_copy_next_retry(b); return ((ret == 0) ? ret_code : ret); }
bool OpenSSLCryptoKeyRSA::verifySHA1PKCS1Base64Signature(const unsigned char * hashBuf, unsigned int hashLen, const char * base64Signature, unsigned int sigLen, hashMethod hm = HASH_SHA1) { // Use the currently loaded key to validate the Base64 encoded signature if (mp_rsaKey == NULL) { throw XSECCryptoException(XSECCryptoException::RSAError, "OpenSSL:RSA - Attempt to validate signature with empty key"); } char* cleanedBase64Signature; unsigned int cleanedBase64SignatureLen = 0; cleanedBase64Signature = XSECCryptoBase64::cleanBuffer(base64Signature, sigLen, cleanedBase64SignatureLen); ArrayJanitor<char> j_cleanedBase64Signature(cleanedBase64Signature); int sigValLen; unsigned char* sigVal = new unsigned char[sigLen + 1]; ArrayJanitor<unsigned char> j_sigVal(sigVal); EVP_ENCODE_CTX m_dctx; EVP_DecodeInit(&m_dctx); int rc = EVP_DecodeUpdate(&m_dctx, sigVal, &sigValLen, (unsigned char *) cleanedBase64Signature, cleanedBase64SignatureLen); if (rc < 0) { throw XSECCryptoException(XSECCryptoException::RSAError, "OpenSSL:RSA - Error during Base64 Decode"); } int t = 0; EVP_DecodeFinal(&m_dctx, &sigVal[sigValLen], &t); sigValLen += t; // Now decrypt unsigned char * decryptBuf; // Decrypt will always be longer than (RSA_len(key) - 11) decryptBuf = new unsigned char [RSA_size(mp_rsaKey)]; ArrayJanitor<unsigned char> j_decryptBuf(decryptBuf); // Note at this time only supports PKCS1 padding // As that is what is defined in the standard. // If this ever changes we will need to pass some paramaters // into this function to allow it to determine what the // padding should be and what the message digest OID should // be. int decryptSize = RSA_public_decrypt(sigValLen, sigVal, decryptBuf, mp_rsaKey, RSA_PKCS1_PADDING); if (decryptSize < 0) { /* throw XSECCryptoException(XSECCryptoException::RSAError, "OpenSSL:RSA::verify() - Error decrypting signature"); */ // Really - this is a failed signature check, not an exception! return false; } /* Check the OID */ int oidLen = 0; unsigned char * oid = getRSASigOID(hm, oidLen); if (oid == NULL) { throw XSECCryptoException(XSECCryptoException::RSAError, "OpenSSL:RSA::verify() - Unsupported HASH algorithm for RSA"); } if (decryptSize != (int) (oidLen + hashLen) || hashLen != oid[oidLen-1]) { return false; } for (t = 0; t < oidLen; ++t) { if (oid[t] != decryptBuf[t]) { return false; } } for (;t < decryptSize; ++t) { if (hashBuf[t-oidLen] != decryptBuf[t]) { return false; } } // All OK return true; }
//-------------------------------------------------- // Reads in signed XML document and extracts the desired data file // pSigDoc - signed document object if exists. Can be NULL // szFileName - digidoc filename // szDataFileName - name of the file where to store embedded data. // szDocId - DataFile Id atribute value // szCharset - convert DataFile content to charset //-------------------------------------------------- EXP_OPTION int ddocExtractDataFile(SignedDoc* pSigDoc, const char* szFileName, const char* szDataFileName, const char* szDocId, const char* szCharset) { FILE *fIn = 0, *fOut = 0; int err = ERR_OK, i, nRead, lt, la, lc, j, ld, lb, l, eState = 0, fs = 0; long len, lExtr = 0, lSize = 0; char chars[1050], tag[100], attr[100], con[1030], dec[70], b64line[70]; unsigned char b64 = 0, nNc = 0, bFound = 0; void *pBuf; EVP_ENCODE_CTX ectx; #ifdef WIN32 wchar_t *convFileName = 0, *convDataFileName = 0; i= 0; err = utf82unicode((const char*)szFileName, (char**)&convFileName, &i); ddocDebug(3, "ddocExtractDataFile", "file: %s, conv-file: %s len: %d", szFileName, convFileName, i); i= 0; err = utf82unicode((const char*)szDataFileName, (char**)&convDataFileName, &i); ddocDebug(3, "ddocExtractDataFile", "dfile: %s, conv-dfile: %s len: %d", szDataFileName, convDataFileName, i); #endif RETURN_IF_NULL_PARAM(szFileName); RETURN_IF_NULL_PARAM(szDataFileName); RETURN_IF_NULL_PARAM(szDocId); RETURN_IF_NULL_PARAM(szCharset); clearErrors(); ddocDebug(3, "ddocExtractDataFile", "SigDoc: %s, docid: %s, digidoc: %s, file: %s, charset: %s", (pSigDoc ? "OK" : "NULL"), szDocId, szFileName, szDataFileName, szCharset); if(szCharset && !strcmp(szCharset, "NO-CHANGE")) nNc = 1; // try reading from memory if already cached? nRead = ddocGetDataFileCachedData(pSigDoc, szDocId, &pBuf, &len); if(pBuf) { // gotcha ddocDebug(3, "ddocSaxExtractDataFile", "Using cached data: %d bytes", len); #ifdef WIN32 if((fOut = _wfopen(convDataFileName, L"wb")) != NULL) { #else if((fOut = fopen(szDataFileName, "wb")) != NULL) { #endif fwrite(pBuf, 1, len, fOut); fclose(fOut); } else { free(pBuf); ddocDebug(1, "ddocSaxExtractDataFile", "Error writing file: %s", szDataFileName); SET_LAST_ERROR_RETURN_CODE(ERR_FILE_WRITE); } free(pBuf); return nRead; } // open ddoc file #ifdef WIN32 if((fIn = _wfopen(convFileName, L"rb")) != NULL) { #else if((fIn = fopen(szFileName, "rb")) != NULL) { #endif ddocDebug(3, "ddocExtractDataFile", "Opened ddoc-file: %s", szFileName); do { nRead = fread(chars, 1, 1024, fIn); chars[nRead] = 0; ddocDebug(6, "ddocExtractDataFile", "Parsing %d bytes: \n%s\n", nRead, chars); // handle read data for(i = 0; i < nRead; i++) { switch(eState) { case ST_START: // search '<?xml' if(chars[i] == '<' && !strncmp(chars+i, "<?xml", 5)) { eState = ST_XML; i += 4; } break; case ST_XML: // search '<' if(chars[i] == '<') { eState = ST_TAG_NM; lt = 0; tag[lt] = 0; } break; case ST_TAG_NM: // read tag name if(isalnum(chars[i]) || chars[i] == ':' || chars[i] == '/') { if(lt < sizeof(tag)-1) { tag[lt] = chars[i]; tag[++lt] = 0; } else { ddocDebug(1, "ddocSaxExtractDataFile", "Invalid xml tag-len > %d", sizeof(tag)); SET_LAST_ERROR_RETURN_CODE(ERR_FILE_READ); } } else if(chars[i] == '>') { // tag ended - content eState = ST_CON; } else { // expecting atributes eState = ST_TAG_WS; } break; case ST_TAG_WS: if(chars[i] == '>') { if(bFound) { eState = ST_DF_CON; if(b64) EVP_DecodeInit(&ectx); } else eState = ST_CON; // tag endded - content lc = 0; con[lc] = 0; } else if(isalnum(chars[i])) { eState = ST_ATTR_NM; // attr name started la = 0; attr[la] = chars[i]; attr[++la] = 0; } break; case ST_ATTR_NM: if(isalnum(chars[i])) { if(la < (int)sizeof(attr)-1) { attr[la] = chars[i]; attr[++la] = 0; } else ddocDebug(1, "ddocExtractDataFile", "Truncating attr name: %s", attr); break; //19.11.08 added support for ' } else if(chars[i] == '\"'/*|| chars[i] == '\''*/) { eState = ST_ATTR_CON; lc = 0; con[lc] = 0; fs = 2; } else if(chars[i] == '\'' && fs==0) { eState = ST_ATTR_CON; lc = 0; con[lc] = 0; fs = 1; } else { eState = ST_ATTR_WS; } break; case ST_ATTR_WS: //19.11.08 added support for ' if(chars[i] == '\"'/*|| chars[i] == '\''*/) { eState = ST_ATTR_CON; lc = 0; con[lc] = 0; } else if(chars[i] == '\'' && fs==1) { eState = ST_ATTR_CON; lc = 0; con[lc] = 0; } else { eState = ST_TAG_WS; } break; case ST_ATTR_CON: //19.11.08 added support for ' if(chars[i] != '\"' /*&& chars[i] != '\''*/) { if(lc < (int)sizeof(con)-1) { con[lc] = chars[i]; con[++lc] = 0; } else ddocDebug(1, "ddocExtractDataFile", "Truncating attr content: %s", attr); } else if(chars[i] == '\'' && fs==1) { if(lc < (int)sizeof(con)-1) { con[lc] = chars[i]; con[++lc] = 0; } else ddocDebug(1, "ddocExtractDataFile", "Truncating attr content: %s", attr); } else { eState = ST_TAG_WS; // attribute value complete if(!strcmp(tag, "DataFile")) { // ddocDebug(3, "ddocSaxExtractDataFile", "DataFile start, attr: %s", attr); if(!strcmp(attr, "ContentType")) { b64 = (!strcmp(con, "EMBEDDED_BASE64")) ? 1 : 0; lb = 0; b64line[0] = 0; } if(!strcmp(attr, "Size") && bFound) { lSize = atol(con); } if(!strcmp(attr, "Id")) { ddocDebug(3, "ddocSaxExtractDataFile", "Found Id: %s searching id: %s", con, szDocId); if(!strcmp(con, szDocId)) { bFound = 1; #ifdef WIN32 fOut = _wfopen(convDataFileName, L"wb"); ddocDebug(3, "ddocSaxExtractDataFile", "Opening file: %s handle: %s", convDataFileName, (fOut ? "OK" : "NULL")); #else fOut = fopen(szDataFileName, "wb"); ddocDebug(3, "ddocSaxExtractDataFile", "Opening file: %s handle: %s", szDataFileName, (fOut ? "OK" : "NULL")); #endif if(!fOut) { SET_LAST_ERROR(ERR_FILE_WRITE); err = ERR_FILE_WRITE; return err; } } } } } break; case ST_CON: if(chars[i] == '<') { eState = ST_TAG_NM; lt = 0; tag[lt] = 0; } else { //con[lc] = chars[i]; //con[++lc] = 0; } break; case ST_DF_START: // find tag end if(chars[i] == '>') { eState = ST_DF_CON; lc = 0; con[lc] = 0; if(b64) EVP_DecodeInit(&ectx); } break; case ST_DF_CON: if(chars[i] == '<') { eState = ST_DF_TAG; lt = 0; tag[lt] = 0; } else { if(lc < (int)sizeof(con) - 1) { if(b64 && !nNc) { for(l = 0; l < lc; ) { while(lb < 64 && l < lc && l < sizeof(con)) { if(con[l] != '\n' && con[l] != '\r') b64line[lb++] = con[l]; l++; } if(lb == 64) { b64line[lb++] = '\n'; b64line[lb] = 0; ld = sizeof(dec); dec[0] = 0; EVP_DecodeUpdate(&ectx, (unsigned char*)dec, &ld, (unsigned char*)b64line, lb); lExtr += ld; if(ld > 0) fwrite(dec, 1, ld, fOut); lb = 0; } } } else if(nNc || !b64) { lExtr += lc; fwrite(con, 1, lc, fOut); } lc = 0; } if(lc < sizeof(con)-1) { con[lc] = chars[i]; con[++lc] = 0; } } break; case ST_DF_TAG: if(/*isalnum(chars[i]) || chars[i] == ':' || chars[i] == '/' ||*/ chars[i] != '>') { if(lt < sizeof(tag)-1) { tag[lt] = chars[i]; tag[++lt] = 0; } else { ddocDebug(1, "ddocSaxExtractDataFile", "Invalid xml tag-len > %d", sizeof(tag)); SET_LAST_ERROR_RETURN_CODE(ERR_FILE_READ); } } else { // DF intenal tag name ready if(!strcmp(tag, "/DataFile")) { // end of DF eState = ST_DF_END; } else { // wrong tag - this is content if(lc < sizeof(con)-1) { con[lc] = '<'; for(j = 0; j < lt; j++) con[++lc] = tag[j]; con[++lc] = '>'; con[++lc] = 0; } eState = ST_DF_CON; } } if(eState != ST_DF_END) break; case ST_DF_END: if(b64 && !nNc) { if(lc > 0) { for(l = 0; l < lc; ) { while(lb < 64 && l < lc) { if(con[l] != '\n' && con[l] != '\r') b64line[lb++] = con[l]; l++; } b64line[lb++] = '\n'; b64line[lb] = 0; ld = sizeof(dec); dec[0] = 0; EVP_DecodeUpdate(&ectx, (unsigned char*)dec, &ld, (unsigned char*)b64line, lb); lExtr += ld; if(ld > 0) fwrite(dec, 1, ld, fOut); lb = 0; } } ld = 0; dec[ld] = 0; EVP_DecodeFinal(&ectx, (unsigned char*)dec, &ld); lExtr += ld; if(ld) fwrite(dec, 1, ld, fOut); } else if(nNc || !b64) { if(lc) { lExtr += lc; fwrite(con, 1, lc, fOut); lc = 0; } } i = sizeof(chars); //AM 24.09.08 RIK eState = ST_DF_END_END; break; } } //AM 24.09.08 RIK ST_DF_END to ST_DF_END_END_END } while(nRead > 0 && !err && eState < ST_DF_END_END); } else { ddocDebug(1, "ddocExtractDataFile", "Error reading file: %s", szFileName); SET_LAST_ERROR(ERR_FILE_READ); } if(fIn) fclose(fIn); if(fOut) fclose(fOut); if(!nNc && lSize != lExtr) { ddocDebug(1, "ddocExtractDataFile", "Warning! Extracted: %ld bytes but expected: %ld bytes", lExtr, lSize); //SET_LAST_ERROR(ERR_FILE_READ); //err = ERR_FILE_READ; } if(!bFound) { ddocDebug(1, "ddocExtractDataFile", "DF: %s not found", szDocId); SET_LAST_ERROR(ERR_FILE_WRITE); err = ERR_FILE_WRITE; } ddocDebug(3, "ddocExtractDataFile", "Extracted DF: %s to %s size: %ld expected: %ld", szDocId, szDataFileName, lExtr, lSize); #ifdef WIN32 free(convFileName); free(convDataFileName); #endif return err; }
/* * \fn hip_xmlrpc_parse_response() * * \param mode is this an XML RPC GET/PUT? store response in hit/addr? * \param xmldata pointer to XML character data * \param len length of XML data * \param value ptr for storing response value * \param value_len ptr to the length of the value buffer and for * storing response value length * * \return For GETs, the address or HIT is returned in addr or hit, * and 0 is returned for success. * For PUTs, the XML RPC return code is returned, * which is 0 for success, or 1 or 2. * -1 is returned on error. */ int hip_xmlrpc_parse_response(int mode, char *xmldata, int len, char *value, int *value_len) { xmlDocPtr doc = NULL; xmlNodePtr node, node_val; int retval = -10, i; xmlChar *data; EVP_ENCODE_CTX ctx; /* log_(NORM, "Got the DHT response (content-length=%d):\n%s\n", * len, xmldata); // */ if ((doc = xmlParseMemory(xmldata, len)) == NULL) { goto parse_response_exit; } node = xmlDocGetRootElement(doc); /* <methodResponse> */ if (node->children) { node = node->children; /* <params> */ } node = node->children; if (!node) /* <param> */ { goto parse_response_exit; } node_val = NULL; if (!strcmp((char *)node->name, "param") && node->children && !strcmp((char *)node->children->name, "value")) { node_val = node->children->children; } if (!node_val) { goto parse_response_exit; } switch (mode & 0x000F) { case XMLRPC_MODE_PUT: /* retrieve status code only */ case XMLRPC_MODE_RM: data = xmlNodeGetContent(node_val); /* status code is first int that we encounter */ if (strcmp((char *)node_val->name, "int") == 0) { sscanf((const char *)data, "%d", &retval); xmlFree(data); goto parse_response_exit; } break; case XMLRPC_MODE_GET: /* retrieve address or HIT */ /* <?xml version="1.0" encoding="ISO-8859-1"?> * <methodResponse> * <params><param><value><array><data> * <value><array><data> * <value><base64>AgAAAMCoAQAAAAAAA==</base64></value> * <value><base64>AgAAAMCoAgcAAAAAA==</base64></value> * </data></array></value> * <value><base64></base64></value> * </data></array></value></param></params> * </methodResponse> */ if (!strcmp((char *)node_val->name, "array") && node_val->children && !strcmp((char *)node_val->children->name, "data")) { node = node_val->children->children; } if (!strcmp((char *)node->name, "value") && node->children && !strcmp((char *)node->children->name, "array")) { node = node->children->children; /* <data> */ } /* step through array of responses */ for (node = node->children; node; node = node->next) { node_val = node->children; /* <value><base64> */ if ((!node_val) || (strcmp((char *)node_val->name, "base64"))) { continue; } data = xmlNodeGetContent(node_val); /* protect against unusually large values */ if (strlen((char *)data) > ((unsigned)(((*value_len + 2) / 3) * 4) + 1)) { xmlFree(data); continue; } /* log_(NORM, "XMLRPC GET: got the value:\n%s\n", * data); */ /* decode base64 into value pointer */ /* *value_len = EVP_DecodeBlock((unsigned char *)value, */ /* data, strlen((char *)data)); */ EVP_DecodeInit(&ctx); retval = EVP_DecodeUpdate(&ctx, (__u8 *)value, &i, (__u8 *)data, strlen((char *)data)); if (retval < 0) { xmlFree(data); continue; } *value_len = i; EVP_DecodeFinal(&ctx, data, &i); retval = 0; xmlFree(data); /* the last value encountered will be returned */ } /* end for */ /* placemark and other tags are ignored */ break; } parse_response_exit: if (doc != NULL) { xmlFreeDoc(doc); } return(retval); }
int FMT_decrypt_stream(char *id, byte_string_t key, FILE *infp, FILE *outfp, params_t params) { byte_string_t U; byte_string_t K, V; crypto_ctx_t ctx; unsigned char in[crypt_buf_size]; unsigned char out[200]; //TODO: what should this be? int inl, outl; unsigned char data[1024]; int count; EVP_ENCODE_CTX mime; int result = 0; char *s, slen; int status; advance_to("-----BEGIN IBE-----", infp); advance_to("U:", infp); mime_get(U, infp); slen = strlen(id) + 2; s = (char *) alloca(sizeof(char) * slen); for(;;) { advance_to("ID:", infp); if (feof(infp)) { //ID not found return 0; } fgets(s, slen, infp); if (s[strlen(id)] == '\n') { //correct length? if (!strncmp(s, id, strlen(id))) { //compares? break; //email has ID for us } } } advance_to("V:", infp); mime_get(V, infp); status = IBE_reveal_key(K, U, V, key, params); if (status != 1) { fprintf(outfp, "WARNING: KMAC MISMATCH. INVALID CIPHERTEXT!\n"); byte_string_clear(V); byte_string_clear(K); return result; } advance_to("W:", infp); crypto_ctx_init(ctx); crypto_decrypt_init(ctx, K); EVP_DecodeInit(&mime); for (;;) { fgets(in, crypt_buf_size, infp); inl = strlen(in); if (inl < 0) { fprintf(stderr, "read error\n"); exit(1); } if (inl < 2) break; EVP_DecodeUpdate(&mime, data, &count, in, inl); crypto_decrypt_update(ctx, out, &outl, data, count); fwrite(out, 1, outl, outfp); } EVP_DecodeFinal(&mime, data, &count); crypto_decrypt_update(ctx, out, &outl, data, count); fwrite(out, 1, outl, outfp); if (1 != crypto_decrypt_final(ctx, out, &outl)) { fprintf(outfp, "crypto_decrypt_final() failed!\n"); } else { result = 1; } fwrite(out, 1, outl, outfp); crypto_ctx_clear(ctx); byte_string_clear(K); byte_string_clear(U); byte_string_clear(V); return result; }
static void sign_req (int fd, void *unused) { char thefile[80], cmd_buf[300], p7[3000]; int i, num; unsigned char *data, *asn1; int32_t msglen; BIO *bio = NULL; FILE *fp; struct stat blah; X509_REQ *req = NULL; EVP_ENCODE_CTX ctx; if (recv(fd, (char *)&msglen, sizeof(int32_t), MSG_WAITALL) < sizeof(int32_t)) { return; } msglen = ntohl(msglen); if (msglen > 3000) { return; } if ((data = (unsigned char *)malloc(msglen)) == NULL) { return; } if ((asn1 = (unsigned char *)malloc(msglen)) == NULL) { free(data); return; } if (recv(fd, (char *)data, msglen, MSG_WAITALL) < msglen) { free(data); return; } EVP_DecodeInit(&ctx); EVP_DecodeUpdate(&ctx, asn1, &i, data, msglen); num = i; EVP_DecodeFinal(&ctx, &(asn1[i]), &i); num += i; free(data); if ((bio = BIO_new_mem_buf(asn1, num)) == NULL) { free(asn1); goto no_cert; } if ((req = d2i_X509_REQ_bio(bio, NULL)) == NULL) { free(asn1); goto no_cert; } free(asn1); BIO_free(bio); bio = NULL; unique++; memset(thefile, 0, sizeof(thefile)); snprintf(thefile, sizeof(thefile), "%dreq.pem", unique); if ((fp = fopen(thefile, "w+")) == NULL) { goto no_cert; } if ((bio = BIO_new(BIO_s_file())) == NULL) { fprintf(stderr, "unable to create bio for CSR\n"); goto no_cert; } BIO_set_fp(bio, fp, BIO_NOCLOSE); PEM_write_bio_X509_REQ(bio, req); (void)BIO_flush(bio); BIO_free(bio); bio = NULL; fclose(fp); snprintf(cmd_buf, sizeof(cmd_buf), "openssl ca " "-policy policy_anything -batch -notext " "-config ./conf/openssl.cnf " "-out %dcert.pem -in %dreq.pem", unique, unique); system(cmd_buf); unlink(thefile); snprintf(thefile, sizeof(thefile), "%dcert.pem", unique); if ((stat(thefile, &blah) < 0) || (blah.st_size < 1)) { goto no_cert; } snprintf(cmd_buf, sizeof(cmd_buf), "openssl crl2pkcs7 " "-certfile %dcert.pem -outform DER -out %dder.p7 -nocrl", unique, unique); system(cmd_buf); unlink(thefile); snprintf(thefile, sizeof(thefile), "%dder.p7", unique); if (stat(thefile, &blah) < 0) { goto no_cert; } i = blah.st_size; printf("DER-encoded P7 is %d bytes\n", i); if ((data = (unsigned char *)malloc(blah.st_size*2)) == NULL) { goto no_cert; } if ((fp = fopen(thefile, "r")) == NULL) { free(data); goto no_cert; } if (fread(p7, 1, sizeof(p7), fp) < blah.st_size) { free(data); goto no_cert; } fclose(fp); unlink(thefile); i = 0; EVP_EncodeInit(&ctx); EVP_EncodeUpdate(&ctx, data, &i, (unsigned char *)p7, blah.st_size); num = i; EVP_EncodeFinal(&ctx, (unsigned char *)&(data[i]), &i); num += i; printf("PEM-encoded P7 is %d bytes\n", num); msglen = num; msglen = htonl(msglen); send(fd, (char *)&msglen, sizeof(int32_t), 0); send(fd, (char *)data, num, 0); free(data); no_cert: BIO_free(bio); srv_rem_input(srvctx, fd); close(fd); return; }
static int b64_read(BIO *b, char *out, int outl) { int ret = 0, i, ii, j, k, x, n, num, ret_code = 0; BIO_B64_CTX *ctx; uint8_t *p, *q; if (out == NULL) { return 0; } ctx = (BIO_B64_CTX *) b->ptr; if (ctx == NULL || b->next_bio == NULL) { return 0; } BIO_clear_retry_flags(b); if (ctx->encode != B64_DECODE) { ctx->encode = B64_DECODE; ctx->buf_len = 0; ctx->buf_off = 0; ctx->tmp_len = 0; EVP_DecodeInit(&ctx->base64); } // First check if there are bytes decoded/encoded if (ctx->buf_len > 0) { assert(ctx->buf_len >= ctx->buf_off); i = ctx->buf_len - ctx->buf_off; if (i > outl) { i = outl; } assert(ctx->buf_off + i < (int)sizeof(ctx->buf)); OPENSSL_memcpy(out, &ctx->buf[ctx->buf_off], i); ret = i; out += i; outl -= i; ctx->buf_off += i; if (ctx->buf_len == ctx->buf_off) { ctx->buf_len = 0; ctx->buf_off = 0; } } // At this point, we have room of outl bytes and an empty buffer, so we // should read in some more. ret_code = 0; while (outl > 0) { if (ctx->cont <= 0) { break; } i = BIO_read(b->next_bio, &(ctx->tmp[ctx->tmp_len]), B64_BLOCK_SIZE - ctx->tmp_len); if (i <= 0) { ret_code = i; // Should we continue next time we are called? if (!BIO_should_retry(b->next_bio)) { ctx->cont = i; // If buffer empty break if (ctx->tmp_len == 0) { break; } else { // Fall through and process what we have i = 0; } } else { // else we retry and add more data to buffer break; } } i += ctx->tmp_len; ctx->tmp_len = i; // We need to scan, a line at a time until we have a valid line if we are // starting. if (ctx->start && (BIO_test_flags(b, BIO_FLAGS_BASE64_NO_NL))) { // ctx->start = 1; ctx->tmp_len = 0; } else if (ctx->start) { q = p = (uint8_t *)ctx->tmp; num = 0; for (j = 0; j < i; j++) { if (*(q++) != '\n') { continue; } // due to a previous very long line, we need to keep on scanning for a // '\n' before we even start looking for base64 encoded stuff. if (ctx->tmp_nl) { p = q; ctx->tmp_nl = 0; continue; } k = EVP_DecodeUpdate(&(ctx->base64), (uint8_t *)ctx->buf, &num, p, q - p); if (k <= 0 && num == 0 && ctx->start) { EVP_DecodeInit(&ctx->base64); } else { if (p != (uint8_t *)&(ctx->tmp[0])) { i -= (p - (uint8_t *)&(ctx->tmp[0])); for (x = 0; x < i; x++) { ctx->tmp[x] = p[x]; } } EVP_DecodeInit(&ctx->base64); ctx->start = 0; break; } p = q; } // we fell off the end without starting if (j == i && num == 0) { // Is this is one long chunk?, if so, keep on reading until a new // line. if (p == (uint8_t *)&(ctx->tmp[0])) { // Check buffer full if (i == B64_BLOCK_SIZE) { ctx->tmp_nl = 1; ctx->tmp_len = 0; } } else if (p != q) { // finished on a '\n' n = q - p; for (ii = 0; ii < n; ii++) { ctx->tmp[ii] = p[ii]; } ctx->tmp_len = n; } // else finished on a '\n' continue; } else { ctx->tmp_len = 0; } } else if (i < B64_BLOCK_SIZE && ctx->cont > 0) { // If buffer isn't full and we can retry then restart to read in more // data. continue; } if (BIO_test_flags(b, BIO_FLAGS_BASE64_NO_NL)) { int z, jj; jj = i & ~3; // process per 4 z = EVP_DecodeBlock((uint8_t *)ctx->buf, (uint8_t *)ctx->tmp, jj); if (jj > 2) { if (ctx->tmp[jj - 1] == '=') { z--; if (ctx->tmp[jj - 2] == '=') { z--; } } } // z is now number of output bytes and jj is the number consumed. if (jj != i) { OPENSSL_memmove(ctx->tmp, &ctx->tmp[jj], i - jj); ctx->tmp_len = i - jj; } ctx->buf_len = 0; if (z > 0) { ctx->buf_len = z; } i = z; } else { i = EVP_DecodeUpdate(&(ctx->base64), (uint8_t *)ctx->buf, &ctx->buf_len, (uint8_t *)ctx->tmp, i); ctx->tmp_len = 0; } ctx->buf_off = 0; if (i < 0) { ret_code = 0; ctx->buf_len = 0; break; } if (ctx->buf_len <= outl) { i = ctx->buf_len; } else { i = outl; } OPENSSL_memcpy(out, ctx->buf, i); ret += i; ctx->buf_off = i; if (ctx->buf_off == ctx->buf_len) { ctx->buf_len = 0; ctx->buf_off = 0; } outl -= i; out += i; } BIO_copy_next_retry(b); return ret == 0 ? ret_code : ret; }