static int cms_wrap_init(CMS_KeyAgreeRecipientInfo *kari, const EVP_CIPHER *cipher) { EVP_CIPHER_CTX *ctx = &kari->ctx; const EVP_CIPHER *kekcipher; int keylen = EVP_CIPHER_key_length(cipher); /* If a suitable wrap algorithm is already set nothing to do */ kekcipher = EVP_CIPHER_CTX_cipher(ctx); if (kekcipher) { if (EVP_CIPHER_CTX_mode(ctx) != EVP_CIPH_WRAP_MODE) return 0; return 1; } /* * Pick a cipher based on content encryption cipher. If it is DES3 use * DES3 wrap otherwise use AES wrap similar to key size. */ if (EVP_CIPHER_type(cipher) == NID_des_ede3_cbc) kekcipher = EVP_des_ede3_wrap(); else if (keylen <= 16) kekcipher = EVP_aes_128_wrap(); else if (keylen <= 24) kekcipher = EVP_aes_192_wrap(); else kekcipher = EVP_aes_256_wrap(); return EVP_EncryptInit_ex(ctx, kekcipher, NULL, NULL, NULL); }
static VALUE ossl_cipher_pkcs5_keyivgen(int argc, VALUE *argv, VALUE self) { EVP_CIPHER_CTX *ctx; const EVP_MD *digest; VALUE vpass, vsalt, viter, vdigest; unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH], *salt = NULL; int iter; rb_scan_args(argc, argv, "13", &vpass, &vsalt, &viter, &vdigest); StringValue(vpass); if(!NIL_P(vsalt)){ StringValue(vsalt); if(RSTRING(vsalt)->len != PKCS5_SALT_LEN) rb_raise(eCipherError, "salt must be an 8-octet string"); salt = RSTRING(vsalt)->ptr; } iter = NIL_P(viter) ? 2048 : NUM2INT(viter); digest = NIL_P(vdigest) ? EVP_md5() : GetDigestPtr(vdigest); GetCipher(self, ctx); EVP_BytesToKey(EVP_CIPHER_CTX_cipher(ctx), digest, salt, RSTRING(vpass)->ptr, RSTRING(vpass)->len, iter, key, iv); if (EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, -1) != 1) ossl_raise(eCipherError, NULL); OPENSSL_cleanse(key, sizeof key); OPENSSL_cleanse(iv, sizeof iv); return Qnil; }
int CMAC_Init(CMAC_CTX *ctx, const void *key, size_t keylen, const EVP_CIPHER *cipher, ENGINE *impl) { static unsigned char zero_iv[EVP_MAX_BLOCK_LENGTH]; #ifdef OPENSSL_FIPS if (FIPS_mode()) { /* If we have an ENGINE need to allow non FIPS */ if ((impl || ctx->cctx.engine) && !(ctx->cctx.flags & EVP_CIPH_FLAG_NON_FIPS_ALLOW)) { EVPerr(EVP_F_CMAC_INIT, EVP_R_DISABLED_FOR_FIPS); return 0; } /* Other algorithm blocking will be done in FIPS_cmac_init, * via FIPS_cipherinit(). */ if (!impl && !ctx->cctx.engine) return FIPS_cmac_init(ctx, key, keylen, cipher, NULL); } #endif /* All zeros means restart */ if (!key && !cipher && !impl && keylen == 0) { /* Not initialised */ if (ctx->nlast_block == -1) return 0; if (!EVP_EncryptInit_ex(&ctx->cctx, NULL, NULL, NULL, zero_iv)) return 0; return 1; } /* Initialiase context */ if (cipher && !EVP_EncryptInit_ex(&ctx->cctx, cipher, impl, NULL, NULL)) return 0; /* Non-NULL key means initialisation complete */ if (key) { int bl; if (!EVP_CIPHER_CTX_cipher(&ctx->cctx)) return 0; if (!EVP_CIPHER_CTX_set_key_length(&ctx->cctx, keylen)) return 0; if (!EVP_EncryptInit_ex(&ctx->cctx, NULL, NULL, key, zero_iv)) return 0; bl = EVP_CIPHER_CTX_block_size(&ctx->cctx); if (!EVP_Cipher(&ctx->cctx, ctx->tbl, zero_iv, bl)) return 0; make_kn(ctx->k1, ctx->tbl, bl); make_kn(ctx->k2, ctx->k1, bl); OPENSSL_cleanse(ctx->tbl, bl); /* Reset context again ready for first data block */ if (!EVP_EncryptInit_ex(&ctx->cctx, NULL, NULL, NULL, zero_iv)) return 0; /* Zero tbl so resume works */ memset(ctx->tbl, 0, bl); ctx->nlast_block = 0; } return 1; }
static BUF_MEM * cipher(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, ENGINE *impl, const unsigned char *key, const unsigned char *iv, int enc, const BUF_MEM * in) { BUF_MEM * out = NULL; EVP_CIPHER_CTX * tmp_ctx = NULL; int i; unsigned long flags; check(in, "Invalid arguments"); if (ctx) tmp_ctx = ctx; else { tmp_ctx = EVP_CIPHER_CTX_new(); if (!tmp_ctx) goto err; EVP_CIPHER_CTX_init(tmp_ctx); if (!EVP_CipherInit_ex(tmp_ctx, type, impl, key, iv, enc)) goto err; } flags = EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(tmp_ctx)); if (flags & EVP_CIPH_NO_PADDING) { i = in->length; check((in->length % EVP_CIPHER_block_size(type) == 0), "Data is not of blocklength"); } else i = in->length + EVP_CIPHER_block_size(type); out = BUF_MEM_create(i); if (!out) goto err; if (!EVP_CipherUpdate(tmp_ctx, (unsigned char *) out->data, &i, (unsigned char *) in->data, in->length)) goto err; out->length = i; if (!EVP_CipherFinal_ex(tmp_ctx, (unsigned char *) (out->data + out->length), &i)) goto err; if (!(flags & EVP_CIPH_NO_PADDING)) out->length += i; if (!ctx) EVP_CIPHER_CTX_free(tmp_ctx); return out; err: if (out) BUF_MEM_free(out); if (!ctx && tmp_ctx) EVP_CIPHER_CTX_free(tmp_ctx); return NULL; }
static VALUE ossl_cipher_name(VALUE self) { EVP_CIPHER_CTX *ctx; GetCipher(self, ctx); return rb_str_new2(EVP_CIPHER_name(EVP_CIPHER_CTX_cipher(ctx))); }
/* * PUBLIC */ const EVP_CIPHER * GetCipherPtr(VALUE obj) { EVP_CIPHER_CTX *ctx; SafeGetCipher(obj, ctx); return EVP_CIPHER_CTX_cipher(ctx); }
static int aead_rc4_sha1_tls_get_rc4_state(const EVP_AEAD_CTX *ctx, const RC4_KEY **out_key) { const AEAD_TLS_CTX *tls_ctx = (AEAD_TLS_CTX*) ctx->aead_state; if (EVP_CIPHER_CTX_cipher(&tls_ctx->cipher_ctx) != EVP_rc4()) { return 0; } *out_key = (const RC4_KEY*) tls_ctx->cipher_ctx.cipher_data; return 1; }
int aes_init (crypt_data_t* crypt_data, crypt_init_t crypt_init) { const EVP_CIPHER* cipher = 0; switch (crypt_data->keysize) { case 16: cipher = EVP_aes_128_cbc (); break; case 24: cipher = EVP_aes_192_cbc (); break; case 32: cipher = EVP_aes_256_cbc (); break; default: fprintf (stderr, "Invalid key size.\n"); return -1; } EVP_CIPHER_CTX_init (&crypt_data->ctx); if (!crypt_init (&crypt_data->ctx, cipher, NULL, crypt_data->keybuf, crypt_data->ivbuf)) { fprintf (stderr, "OpenSSL initialization failed.\n"); return 1; } if (verbose) { fprintf (stderr, "EVP Initialized\n Algorithm: %s\n", EVP_CIPHER_name (EVP_CIPHER_CTX_cipher (&crypt_data->ctx))); fprintf (stderr, " IV: "); pp_buf (stderr, crypt_data->ivbuf, crypt_data->ivsize, 16, 2); fprintf (stderr, " Key: "); pp_buf (stderr, crypt_data->keybuf, crypt_data->keysize, 16, 2); } crypt_data->buf_size = INBUFSIZE; crypt_data->out_buf = (char*)malloc (crypt_data->buf_size + EVP_CIPHER_CTX_block_size (&crypt_data->ctx)); crypt_data->in_buf = (char*)malloc (crypt_data->buf_size); if (!crypt_data->out_buf || !crypt_data->in_buf) { fprintf (stderr, "Unable to allocate memory.\n"); return 1; } return 0; }
static LUA_FUNCTION(openssl_cipher_ctx_info) { EVP_CIPHER_CTX *ctx = CHECK_OBJECT(1, EVP_CIPHER_CTX, "openssl.evp_cipher_ctx"); lua_newtable(L); AUXILIAR_SET(L, -1, "block_size", EVP_CIPHER_CTX_block_size(ctx), integer); AUXILIAR_SET(L, -1, "key_length", EVP_CIPHER_CTX_key_length(ctx), integer); AUXILIAR_SET(L, -1, "iv_length", EVP_CIPHER_CTX_iv_length(ctx), integer); AUXILIAR_SET(L, -1, "flags", EVP_CIPHER_CTX_flags(ctx), integer); AUXILIAR_SET(L, -1, "nid", EVP_CIPHER_CTX_nid(ctx), integer); AUXILIAR_SET(L, -1, "type", EVP_CIPHER_CTX_mode(ctx), integer); AUXILIAR_SET(L, -1, "mode", EVP_CIPHER_CTX_type(ctx), integer); AUXILIAR_SETOBJECT(L, EVP_CIPHER_CTX_cipher(ctx), "openssl.evp_cipher", -1, "cipher"); return 1; }
static int cms_wrap_init(CMS_KeyAgreeRecipientInfo *kari, const EVP_CIPHER *cipher) { EVP_CIPHER_CTX *ctx = kari->ctx; const EVP_CIPHER *kekcipher; #ifndef OPENSSL_NO_AES int keylen = EVP_CIPHER_key_length(cipher); #endif /* If a suitable wrap algorithm is already set nothing to do */ kekcipher = EVP_CIPHER_CTX_cipher(ctx); if (kekcipher) { if (EVP_CIPHER_CTX_mode(ctx) != EVP_CIPH_WRAP_MODE) return 0; return 1; } /* * Pick a cipher based on content encryption cipher. If it is DES3 use * DES3 wrap otherwise use AES wrap similar to key size. */ #if !defined(OPENSSL_NO_DES) && !defined(OPENSSL_NO_SHA) /* EVP_des_ede3_wrap() depends on EVP_sha1() */ if (EVP_CIPHER_type(cipher) == NID_des_ede3_cbc) kekcipher = EVP_des_ede3_wrap(); else #endif #ifndef OPENSSL_NO_SMS4 if (EVP_CIPHER_type(cipher) == NID_sms4_cbc || EVP_CIPHER_type(cipher) == NID_sm1_cbc || EVP_CIPHER_type(cipher) == NID_ssf33_cbc) kekcipher = EVP_sms4_wrap(); else #endif #ifndef OPENSSL_NO_AES if (keylen <= 16) kekcipher = EVP_aes_128_wrap(); else if (keylen <= 24) kekcipher = EVP_aes_192_wrap(); else kekcipher = EVP_aes_256_wrap(); #endif if (kekcipher == NULL) return 0; return EVP_EncryptInit_ex(ctx, kekcipher, NULL, NULL, NULL); }
int CMAC_Init(CMAC_CTX *ctx, const void *key, size_t keylen, const EVP_CIPHER *cipher, ENGINE *impl) { static unsigned char zero_iv[EVP_MAX_BLOCK_LENGTH]; /* All zeros means restart */ if (!key && !cipher && !impl && keylen == 0) { /* Not initialised */ if (ctx->nlast_block == -1) return 0; if (!EVP_EncryptInit_ex(&ctx->cctx, NULL, NULL, NULL, zero_iv)) return 0; memset(ctx->tbl, 0, EVP_CIPHER_CTX_block_size(&ctx->cctx)); ctx->nlast_block = 0; return 1; } /* Initialiase context */ if (cipher && !EVP_EncryptInit_ex(&ctx->cctx, cipher, impl, NULL, NULL)) return 0; /* Non-NULL key means initialisation complete */ if (key) { int bl; if (!EVP_CIPHER_CTX_cipher(&ctx->cctx)) return 0; if (!EVP_CIPHER_CTX_set_key_length(&ctx->cctx, keylen)) return 0; if (!EVP_EncryptInit_ex(&ctx->cctx, NULL, NULL, key, zero_iv)) return 0; bl = EVP_CIPHER_CTX_block_size(&ctx->cctx); if (!EVP_Cipher(&ctx->cctx, ctx->tbl, zero_iv, bl)) return 0; make_kn(ctx->k1, ctx->tbl, bl); make_kn(ctx->k2, ctx->k1, bl); OPENSSL_cleanse(ctx->tbl, bl); /* Reset context again ready for first data block */ if (!EVP_EncryptInit_ex(&ctx->cctx, NULL, NULL, NULL, zero_iv)) return 0; /* Zero tbl so resume works */ memset(ctx->tbl, 0, bl); ctx->nlast_block = 0; } return 1; }
static VALUE ossl_cipher_init(int argc, VALUE *argv, VALUE self, int mode) { EVP_CIPHER_CTX *ctx; unsigned char key[EVP_MAX_KEY_LENGTH], *p_key = NULL; unsigned char iv[EVP_MAX_IV_LENGTH], *p_iv = NULL; VALUE pass, init_v; if(rb_scan_args(argc, argv, "02", &pass, &init_v) > 0){ /* * oops. this code mistakes salt for IV. * We deprecated the arguments for this method, but we decided * keeping this behaviour for backward compatibility. */ VALUE cname = rb_class_path(rb_obj_class(self)); rb_warn("arguments for %"PRIsVALUE"#encrypt and %"PRIsVALUE"#decrypt were deprecated; " "use %"PRIsVALUE"#pkcs5_keyivgen to derive key and IV", cname, cname, cname); StringValue(pass); GetCipher(self, ctx); if (NIL_P(init_v)) memcpy(iv, "OpenSSL for Ruby rulez!", sizeof(iv)); else{ StringValue(init_v); if (EVP_MAX_IV_LENGTH > RSTRING_LEN(init_v)) { memset(iv, 0, EVP_MAX_IV_LENGTH); memcpy(iv, RSTRING_PTR(init_v), RSTRING_LEN(init_v)); } else memcpy(iv, RSTRING_PTR(init_v), sizeof(iv)); } EVP_BytesToKey(EVP_CIPHER_CTX_cipher(ctx), EVP_md5(), iv, (unsigned char *)RSTRING_PTR(pass), RSTRING_LENINT(pass), 1, key, NULL); p_key = key; p_iv = iv; } else { GetCipher(self, ctx); } if (EVP_CipherInit_ex(ctx, NULL, NULL, p_key, p_iv, mode) != 1) { ossl_raise(eCipherError, NULL); } return self; }
static VALUE ossl_cipher_init(int argc, VALUE *argv, VALUE self, int mode) { EVP_CIPHER_CTX *ctx; unsigned char key[EVP_MAX_KEY_LENGTH], *p_key = NULL; unsigned char iv[EVP_MAX_IV_LENGTH], *p_iv = NULL; VALUE pass, init_v; if(rb_scan_args(argc, argv, "02", &pass, &init_v) > 0){ /* * oops. this code mistakes salt for IV. * We deprecated the arguments for this method, but we decided * keeping this behaviour for backward compatibility. */ StringValue(pass); GetCipher(self, ctx); if (NIL_P(init_v)) memcpy(iv, "OpenSSL for Ruby rulez!", sizeof(iv)); else{ char *cname = rb_class2name(rb_obj_class(self)); rb_warning("key derivation by %s#encrypt is deprecated; " "use %s::pkcs5_keyivgen instead", cname, cname); StringValue(init_v); if (EVP_MAX_IV_LENGTH > RSTRING(init_v)->len) { memset(iv, 0, EVP_MAX_IV_LENGTH); memcpy(iv, RSTRING(init_v)->ptr, RSTRING(init_v)->len); } else memcpy(iv, RSTRING(init_v)->ptr, sizeof(iv)); } EVP_BytesToKey(EVP_CIPHER_CTX_cipher(ctx), EVP_md5(), iv, RSTRING(pass)->ptr, RSTRING(pass)->len, 1, key, NULL); p_key = key; p_iv = iv; } else { GetCipher(self, ctx); } if (EVP_CipherInit_ex(ctx, NULL, NULL, p_key, p_iv, mode) != 1) { ossl_raise(eCipherError, NULL); } return self; }
int dtls1_enc(SSL *s, int send) { SSL3_RECORD *rec; EVP_CIPHER_CTX *ds; unsigned long l; int bs,i,ii,j,k,n=0; const EVP_CIPHER *enc; if (send) { if (EVP_MD_CTX_md(s->write_hash)) { n=EVP_MD_CTX_size(s->write_hash); if (n < 0) return -1; } ds=s->enc_write_ctx; rec= &(s->s3->wrec); if (s->enc_write_ctx == NULL) enc=NULL; else { enc=EVP_CIPHER_CTX_cipher(s->enc_write_ctx); if ( rec->data != rec->input) /* we can't write into the input stream */ #ifndef OPENSSL_SYS_WINDOWS TINYCLR_SSL_PRINTF("%s:%d: rec->data != rec->input\n", __FILE__, __LINE__); #else TINYCLR_SSL_FPRINTF(OPENSSL_TYPE__FILE_STDERR, "%s:%d: rec->data != rec->input\n", __FILE__, __LINE__); #endif else if ( EVP_CIPHER_block_size(ds->cipher) > 1) { if (RAND_bytes(rec->input, EVP_CIPHER_block_size(ds->cipher)) <= 0) return -1; } } }
/*- * dtls1_enc encrypts/decrypts the record in |s->wrec| / |s->rrec|, respectively. * * Returns: * 0: (in non-constant time) if the record is publically invalid (i.e. too * short etc). * 1: if the record's padding is valid / the encryption was successful. * -1: if the record's padding/AEAD-authenticator is invalid or, if sending, * an internal error occured. */ int dtls1_enc(SSL *s, int send) { SSL3_RECORD *rec; EVP_CIPHER_CTX *ds; unsigned long l; int bs, i, j, k, mac_size = 0; const EVP_CIPHER *enc; if (send) { if (EVP_MD_CTX_md(s->write_hash)) { mac_size = EVP_MD_CTX_size(s->write_hash); if (mac_size < 0) return -1; } ds = s->enc_write_ctx; rec = &(s->s3->wrec); if (s->enc_write_ctx == NULL) enc = NULL; else { enc = EVP_CIPHER_CTX_cipher(s->enc_write_ctx); if (rec->data != rec->input) /* we can't write into the input stream */ fprintf(stderr, "%s:%d: rec->data != rec->input\n", __FILE__, __LINE__); else if (EVP_CIPHER_block_size(ds->cipher) > 1) { if (RAND_bytes(rec->input, EVP_CIPHER_block_size(ds->cipher)) <= 0) return -1; } } } else { if (EVP_MD_CTX_md(s->read_hash)) { mac_size = EVP_MD_CTX_size(s->read_hash); OPENSSL_assert(mac_size >= 0); } ds = s->enc_read_ctx; rec = &(s->s3->rrec); if (s->enc_read_ctx == NULL) enc = NULL; else enc = EVP_CIPHER_CTX_cipher(s->enc_read_ctx); } #ifdef KSSL_DEBUG printf("dtls1_enc(%d)\n", send); #endif /* KSSL_DEBUG */ if ((s->session == NULL) || (ds == NULL) || (enc == NULL)) { memmove(rec->data, rec->input, rec->length); rec->input = rec->data; } else { l = rec->length; bs = EVP_CIPHER_block_size(ds->cipher); if ((bs != 1) && send) { i = bs - ((int)l % bs); /* Add weird padding of upto 256 bytes */ /* we need to add 'i' padding bytes of value j */ j = i - 1; if (s->options & SSL_OP_TLS_BLOCK_PADDING_BUG) { if (s->s3->flags & TLS1_FLAGS_TLS_PADDING_BUG) j++; } for (k = (int)l; k < (int)(l + i); k++) rec->input[k] = j; l += i; rec->length += i; } #ifdef KSSL_DEBUG { unsigned long ui; printf("EVP_Cipher(ds=%p,rec->data=%p,rec->input=%p,l=%ld) ==>\n", ds, rec->data, rec->input, l); printf ("\tEVP_CIPHER_CTX: %d buf_len, %d key_len [%d %d], %d iv_len\n", ds->buf_len, ds->cipher->key_len, DES_KEY_SZ, DES_SCHEDULE_SZ, ds->cipher->iv_len); printf("\t\tIV: "); for (i = 0; i < ds->cipher->iv_len; i++) printf("%02X", ds->iv[i]); printf("\n"); printf("\trec->input="); for (ui = 0; ui < l; ui++) printf(" %02x", rec->input[ui]); printf("\n"); } #endif /* KSSL_DEBUG */ if (!send) { if (l == 0 || l % bs != 0) return 0; } if (EVP_Cipher(ds, rec->data, rec->input, l) < 1) return -1; #ifdef KSSL_DEBUG { unsigned long i; printf("\trec->data="); for (i = 0; i < l; i++) printf(" %02x", rec->data[i]); printf("\n"); } #endif /* KSSL_DEBUG */ if ((bs != 1) && !send) return tls1_cbc_remove_padding(s, rec, bs, mac_size); } return (1); }
int dtls1_enc(SSL *s, int send) { SSL3_RECORD *rec; EVP_CIPHER_CTX *ds; unsigned long l; int bs,i,ii,j,k; const EVP_CIPHER *enc; if (send) { ds=s->enc_write_ctx; rec= &(s->s3->wrec); if (s->enc_write_ctx == NULL) enc=NULL; else { enc=EVP_CIPHER_CTX_cipher(s->enc_write_ctx); if ( rec->data != rec->input) /* we can't write into the input stream */ fprintf(stderr, "%s:%d: rec->data != rec->input\n", __FILE__, __LINE__); else if ( EVP_CIPHER_block_size(ds->cipher) > 1) { if (RAND_bytes(rec->input, EVP_CIPHER_block_size(ds->cipher)) <= 0) return -1; } } } else { ds=s->enc_read_ctx; rec= &(s->s3->rrec); if (s->enc_read_ctx == NULL) enc=NULL; else enc=EVP_CIPHER_CTX_cipher(s->enc_read_ctx); } #ifdef KSSL_DEBUG printf("dtls1_enc(%d)\n", send); #endif /* KSSL_DEBUG */ if ((s->session == NULL) || (ds == NULL) || (enc == NULL)) { memmove(rec->data,rec->input,rec->length); rec->input=rec->data; } else { l=rec->length; bs=EVP_CIPHER_block_size(ds->cipher); if ((bs != 1) && send) { i=bs-((int)l%bs); /* Add weird padding of upto 256 bytes */ /* we need to add 'i' padding bytes of value j */ j=i-1; if (s->options & SSL_OP_TLS_BLOCK_PADDING_BUG) { if (s->s3->flags & TLS1_FLAGS_TLS_PADDING_BUG) j++; } for (k=(int)l; k<(int)(l+i); k++) rec->input[k]=j; l+=i; rec->length+=i; } #ifdef KSSL_DEBUG { unsigned long ui; printf("EVP_Cipher(ds=%p,rec->data=%p,rec->input=%p,l=%ld) ==>\n", (void *)ds,rec->data,rec->input,l); printf("\tEVP_CIPHER_CTX: %d buf_len, %d key_len [%ld %ld], %d iv_len\n", ds->buf_len, ds->cipher->key_len, (unsigned long)DES_KEY_SZ, (unsigned long)DES_SCHEDULE_SZ, ds->cipher->iv_len); printf("\t\tIV: "); for (i=0; i<ds->cipher->iv_len; i++) printf("%02X", ds->iv[i]); printf("\n"); printf("\trec->input="); for (ui=0; ui<l; ui++) printf(" %02x", rec->input[ui]); printf("\n"); } #endif /* KSSL_DEBUG */ if (!send) { if (l == 0 || l%bs != 0) return -1; } EVP_Cipher(ds,rec->data,rec->input,l); #ifdef KSSL_DEBUG { unsigned long ki; printf("\trec->data="); for (ki=0; ki<l; ki++) printf(" %02x", rec->data[ki]); printf("\n"); } #endif /* KSSL_DEBUG */ if ((bs != 1) && !send) { ii=i=rec->data[l-1]; /* padding_length */ i++; if (s->options&SSL_OP_TLS_BLOCK_PADDING_BUG) { /* First packet is even in size, so check */ if ((memcmp(s->s3->read_sequence, "\0\0\0\0\0\0\0\0",8) == 0) && !(ii & 1)) s->s3->flags|=TLS1_FLAGS_TLS_PADDING_BUG; if (s->s3->flags & TLS1_FLAGS_TLS_PADDING_BUG) i--; } /* TLS 1.0 does not bound the number of padding bytes by the block size. * All of them must have value 'padding_length'. */ if (i > (int)rec->length) { /* Incorrect padding. SSLerr() and ssl3_alert are done * by caller: we don't want to reveal whether this is * a decryption error or a MAC verification failure * (see http://www.openssl.org/~bodo/tls-cbc.txt) */ return -1; } for (j=(int)(l-i); j<(int)l; j++) { if (rec->data[j] != ii) { /* Incorrect padding */ return -1; } } rec->length-=i; rec->data += bs; /* skip the implicit IV */ rec->input += bs; rec->length -= bs; } } return(1); }
static int afalg_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { int ciphertype; int ret; afalg_ctx *actx; char ciphername[ALG_MAX_SALG_NAME]; if (ctx == NULL || key == NULL) { ALG_WARN("%s: Null Parameter\n", __func__); return 0; } if (EVP_CIPHER_CTX_cipher(ctx) == NULL) { ALG_WARN("%s: Cipher object NULL\n", __func__); return 0; } actx = EVP_CIPHER_CTX_get_cipher_data(ctx); if (actx == NULL) { ALG_WARN("%s: Cipher data NULL\n", __func__); return 0; } ciphertype = EVP_CIPHER_CTX_nid(ctx); switch (ciphertype) { case NID_aes_128_cbc: strncpy(ciphername, "cbc(aes)", ALG_MAX_SALG_NAME); break; default: ALG_WARN("%s: Unsupported Cipher type %d\n", __func__, ciphertype); return 0; } ciphername[ALG_MAX_SALG_NAME-1]='\0'; if (ALG_AES_IV_LEN != EVP_CIPHER_CTX_iv_length(ctx)) { ALG_WARN("%s: Unsupported IV length :%d\n", __func__, EVP_CIPHER_CTX_iv_length(ctx)); return 0; } /* Setup AFALG socket for crypto processing */ ret = afalg_create_sk(actx, "skcipher", ciphername); if (ret < 1) return 0; ret = afalg_set_key(actx, key, EVP_CIPHER_CTX_key_length(ctx)); if (ret < 1) goto err; /* Setup AIO ctx to allow async AFALG crypto processing */ if (afalg_init_aio(&actx->aio) == 0) goto err; # ifdef ALG_ZERO_COPY pipe(actx->zc_pipe); # endif actx->init_done = MAGIC_INIT_NUM; return 1; err: close(actx->sfd); close(actx->bfd); return 0; }
int ssl3_enc(SSL *s, int send) { SSL3_RECORD *rec; EVP_CIPHER_CTX *ds; unsigned long l; int bs,i; const EVP_CIPHER *enc; if (send) { ds=s->enc_write_ctx; rec= &(s->s3->wrec); if (s->enc_write_ctx == NULL) enc=NULL; else enc=EVP_CIPHER_CTX_cipher(s->enc_write_ctx); } else { ds=s->enc_read_ctx; rec= &(s->s3->rrec); if (s->enc_read_ctx == NULL) enc=NULL; else enc=EVP_CIPHER_CTX_cipher(s->enc_read_ctx); } if ((s->session == NULL) || (ds == NULL) || (enc == NULL)) { memmove(rec->data,rec->input,rec->length); rec->input=rec->data; } else { l=rec->length; bs=EVP_CIPHER_block_size(ds->cipher); /* COMPRESS */ if ((bs != 1) && send) { i=bs-((int)l%bs); /* we need to add 'i-1' padding bytes */ l+=i; rec->length+=i; rec->input[l-1]=(i-1); } if (!send) { if (l == 0 || l%bs != 0) { SSLerr(SSL_F_SSL3_ENC,SSL_R_BLOCK_CIPHER_PAD_IS_WRONG); ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECRYPT_ERROR); return(0); } } EVP_Cipher(ds,rec->data,rec->input,l); if ((bs != 1) && !send) { i=rec->data[l-1]+1; /* SSL 3.0 bounds the number of padding bytes by the block size; * padding bytes (except that last) are arbitrary */ if (i > bs) { SSLerr(SSL_F_SSL3_ENC,SSL_R_BLOCK_CIPHER_PAD_IS_WRONG); ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECRYPT_ERROR); return(0); } rec->length-=i; } } return(1); }
int tls1_enc(SSL *s, int send) { SSL3_RECORD *rec; EVP_CIPHER_CTX *ds; unsigned long l; int bs,i,ii,j,k,n=0; const EVP_CIPHER *enc; if (send) { if (EVP_MD_CTX_md(s->write_hash)) { n=EVP_MD_CTX_size(s->write_hash); TINYCLR_SSL_ASSERT(n >= 0); } ds=s->enc_write_ctx; rec= &(s->s3->wrec); if (s->enc_write_ctx == NULL) enc=NULL; else enc=EVP_CIPHER_CTX_cipher(s->enc_write_ctx); } else { if (EVP_MD_CTX_md(s->read_hash)) { n=EVP_MD_CTX_size(s->read_hash); TINYCLR_SSL_ASSERT(n >= 0); } ds=s->enc_read_ctx; rec= &(s->s3->rrec); if (s->enc_read_ctx == NULL) enc=NULL; else enc=EVP_CIPHER_CTX_cipher(s->enc_read_ctx); } #ifdef KSSL_DEBUG TINYCLR_SSL_PRINTF("tls1_enc(%d)\n", send); #endif /* KSSL_DEBUG */ if ((s->session == NULL) || (ds == NULL) || (enc == NULL)) { TINYCLR_SSL_MEMMOVE(rec->data,rec->input,rec->length); rec->input=rec->data; } else { l=rec->length; bs=EVP_CIPHER_block_size(ds->cipher); if ((bs != 1) && send) { i=bs-((int)l%bs); /* Add weird padding of upto 256 bytes */ /* we need to add 'i' padding bytes of value j */ j=i-1; if (s->options & SSL_OP_TLS_BLOCK_PADDING_BUG) { if (s->s3->flags & TLS1_FLAGS_TLS_PADDING_BUG) j++; } for (k=(int)l; k<(int)(l+i); k++) rec->input[k]=j; l+=i; rec->length+=i; } #ifdef KSSL_DEBUG { unsigned long ui; TINYCLR_SSL_PRINTF("EVP_Cipher(ds=%p,rec->data=%p,rec->input=%p,l=%ld) ==>\n", ds,rec->data,rec->input,l); TINYCLR_SSL_PRINTF("\tEVP_CIPHER_CTX: %d buf_len, %d key_len [%d %d], %d iv_len\n", ds->buf_len, ds->cipher->key_len, DES_KEY_SZ, DES_SCHEDULE_SZ, ds->cipher->iv_len); TINYCLR_SSL_PRINTF("\t\tIV: "); for (i=0; i<ds->cipher->iv_len; i++) TINYCLR_SSL_PRINTF("%02X", ds->iv[i]); TINYCLR_SSL_PRINTF("\n"); TINYCLR_SSL_PRINTF("\trec->input="); for (ui=0; ui<l; ui++) TINYCLR_SSL_PRINTF(" %02x", rec->input[ui]); TINYCLR_SSL_PRINTF("\n"); } #endif /* KSSL_DEBUG */ if (!send) { if (l == 0 || l%bs != 0) { SSLerr(SSL_F_TLS1_ENC,SSL_R_BLOCK_CIPHER_PAD_IS_WRONG); ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECRYPTION_FAILED); return 0; } } EVP_Cipher(ds,rec->data,rec->input,l); #ifdef KSSL_DEBUG { unsigned long i; TINYCLR_SSL_PRINTF("\trec->data="); for (i=0; i<l; i++) TINYCLR_SSL_PRINTF(" %02x", rec->data[i]); TINYCLR_SSL_PRINTF("\n"); } #endif /* KSSL_DEBUG */ if ((bs != 1) && !send) { ii=i=rec->data[l-1]; /* padding_length */ i++; /* NB: if compression is in operation the first packet * may not be of even length so the padding bug check * cannot be performed. This bug workaround has been * around since SSLeay so hopefully it is either fixed * now or no buggy implementation supports compression * [steve] */ if ( (s->options&SSL_OP_TLS_BLOCK_PADDING_BUG) && !s->expand) { /* First packet is even in size, so check */ if ((TINYCLR_SSL_MEMCMP(s->s3->read_sequence, "\0\0\0\0\0\0\0\0",8) == 0) && !(ii & 1)) s->s3->flags|=TLS1_FLAGS_TLS_PADDING_BUG; if (s->s3->flags & TLS1_FLAGS_TLS_PADDING_BUG) i--; } /* TLS 1.0 does not bound the number of padding bytes by the block size. * All of them must have value 'padding_length'. */ if (i > (int)rec->length) { /* Incorrect padding. SSLerr() and ssl3_alert are done * by caller: we don't want to reveal whether this is * a decryption error or a MAC verification failure * (see http://www.openssl.org/~bodo/tls-cbc.txt) */ return -1; } for (j=(int)(l-i); j<(int)l; j++) { if (rec->data[j] != ii) { /* Incorrect padding */ return -1; } } rec->length-=i; } } return(1); }
static int ssl_decrypt_record( dssl_decoder_stack* stack, u_char* data, uint32_t len, u_char** out, uint32_t* out_len, int *buffer_aquired,int *block_size ) { u_char* buf = NULL; uint32_t buf_len = len; int rc = DSSL_RC_OK; const EVP_CIPHER* c = NULL; int func_ret = 0; int i = 0; DEBUG_TRACE3("ssl_decrypt_record - len: %d, out_len: %d, buffer_aquired: %d\n", len, *out_len, buffer_aquired); _ASSERT( stack ); _ASSERT( stack->sess ); _ASSERT( stack->cipher ); rc = ssls_get_decrypt_buffer( stack->sess, &buf, buf_len ); DEBUG_TRACE1("ssl_decrypt_record - calling ssls_get_decrypt_buffer ended. ret: %d\n", rc); // test //memset(buf, 0x77, DSSL_MAX_COMPRESSED_LENGTH); /* for (i = 0; i < 128; i++) { printf("ssl_decrypt_record(1) - buf[%d]: 0x%02X, data: 0x%02X\n", i, buf[i], data[i]); } */ if( rc != DSSL_RC_OK ) return rc; *buffer_aquired = 1; c = EVP_CIPHER_CTX_cipher( stack->cipher ); *block_size = EVP_CIPHER_block_size( c ); DEBUG_TRACE1("ssl_decrypt_record - calling EVP_CIPHER_block_size ended. ret: %d\n", *block_size); if( *block_size != 1 ) { if( len == 0 || (len % *block_size) != 0 ) { DEBUG_TRACE0("ssl_decrypt_record - DSSL_E_SSL_DECRYPTION_ERROR(after EVP_CIPHER_block_size)\n"); return NM_ERROR( DSSL_E_SSL_DECRYPTION_ERROR ); } } func_ret = EVP_Cipher(stack->cipher, buf, data, len ); DEBUG_TRACE1("ssl_decrypt_record - calling EVP_Cipher ret: %d\n", func_ret); buf_len = len; DEBUG_TRACE1("ssl_decrypt_record - buf_len: %d\n", buf_len); /* for (i = 0; i < 128; i++) { printf("ssl_decrypt_record(2) - buf[%d]: 0x%02X, data: 0x%02X\n", i, buf[i], data[i]); } */ /* strip the padding */ if( *block_size > 1 ) { if( buf[len-1] >= buf_len - 1 ) { DEBUG_TRACE0("ssl_decrypt_record - DSSL_E_SSL_DECRYPTION_ERROR(after EVP_Cipher)\n"); return NM_ERROR( DSSL_E_SSL_DECRYPTION_ERROR ); } buf_len -= buf[len-1] + 1; } *out = buf; *out_len = buf_len; return DSSL_RC_OK; }
int ssl3_enc(SSL *s, int send) { SSL3_RECORD *rec; EVP_CIPHER_CTX *ds; unsigned long l; int bs,i; const EVP_CIPHER *enc; if (send) { ds=s->enc_write_ctx; rec= &(s->s3->wrec); if (s->enc_write_ctx == NULL) enc=NULL; else enc=EVP_CIPHER_CTX_cipher(s->enc_write_ctx); } else { ds=s->enc_read_ctx; rec= &(s->s3->rrec); if (s->enc_read_ctx == NULL) enc=NULL; else enc=EVP_CIPHER_CTX_cipher(s->enc_read_ctx); } if ((s->session == NULL) || (ds == NULL) || (enc == NULL)) { memmove(rec->data,rec->input,rec->length); rec->input=rec->data; } else { l=rec->length; bs=EVP_CIPHER_block_size(ds->cipher); /* COMPRESS */ if ((bs != 1) && send) { i=bs-((int)l%bs); /* we need to add 'i-1' padding bytes */ l+=i; /* the last of these zero bytes will be overwritten * with the padding length. */ memset(&rec->input[rec->length], 0, i); rec->length+=i; rec->input[l-1]=(i-1); } if (!send) { if (l == 0 || l%bs != 0) { SSLerr(SSL_F_SSL3_ENC,SSL_R_BLOCK_CIPHER_PAD_IS_WRONG); ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECRYPTION_FAILED); return 0; } /* otherwise, rec->length >= bs */ } EVP_Cipher(ds,rec->data,rec->input,l); if ((bs != 1) && !send) { i=rec->data[l-1]+1; /* SSL 3.0 bounds the number of padding bytes by the block size; * padding bytes (except the last one) are arbitrary */ if (i > bs) { /* Incorrect padding. SSLerr() and ssl3_alert are done * by caller: we don't want to reveal whether this is * a decryption error or a MAC verification failure * (see http://www.openssl.org/~bodo/tls-cbc.txt) */ return -1; } /* now i <= bs <= rec->length */ rec->length-=i; } } return(1); }
/* tls1_enc encrypts/decrypts the record in |s->wrec| / |s->rrec|, respectively. * * Returns: * 0: (in non-constant time) if the record is publically invalid (i.e. too * short etc). * 1: if the record's padding is valid / the encryption was successful. * -1: if the record's padding/AEAD-authenticator is invalid or, if sending, * an internal error occured. */ int tls1_enc(SSL *s, int send) { SSL3_RECORD *rec; EVP_CIPHER_CTX *ds; unsigned long l; int bs,i,j,k,pad=0,ret,mac_size=0; const EVP_CIPHER *enc; if (send) { if (EVP_MD_CTX_md(s->write_hash)) { int n=EVP_MD_CTX_size(s->write_hash); OPENSSL_assert(n >= 0); } ds=s->enc_write_ctx; rec= &(s->s3->wrec); if (s->enc_write_ctx == NULL) enc=NULL; else { int ivlen; enc=EVP_CIPHER_CTX_cipher(s->enc_write_ctx); /* For TLSv1.1 and later explicit IV */ if (s->version >= TLS1_1_VERSION && EVP_CIPHER_mode(enc) == EVP_CIPH_CBC_MODE) ivlen = EVP_CIPHER_iv_length(enc); else ivlen = 0; if (ivlen > 1) { if ( rec->data != rec->input) /* we can't write into the input stream: * Can this ever happen?? (steve) */ fprintf(stderr, "%s:%d: rec->data != rec->input\n", __FILE__, __LINE__); else if (RAND_bytes(rec->input, ivlen) <= 0) return -1; } } } else { if (EVP_MD_CTX_md(s->read_hash)) { int n=EVP_MD_CTX_size(s->read_hash); OPENSSL_assert(n >= 0); } ds=s->enc_read_ctx; rec= &(s->s3->rrec); if (s->enc_read_ctx == NULL) enc=NULL; else enc=EVP_CIPHER_CTX_cipher(s->enc_read_ctx); } #ifdef KSSL_DEBUG printf("tls1_enc(%d)\n", send); #endif /* KSSL_DEBUG */ if ((s->session == NULL) || (ds == NULL) || (enc == NULL)) { memmove(rec->data,rec->input,rec->length); rec->input=rec->data; ret = 1; } else { l=rec->length; bs=EVP_CIPHER_block_size(ds->cipher); if (EVP_CIPHER_flags(ds->cipher)&EVP_CIPH_FLAG_AEAD_CIPHER) { unsigned char buf[13],*seq; seq = send?s->s3->write_sequence:s->s3->read_sequence; if (s->version == DTLS1_VERSION || s->version == DTLS1_BAD_VER) { unsigned char dtlsseq[9],*p=dtlsseq; s2n(send?s->d1->w_epoch:s->d1->r_epoch,p); memcpy(p,&seq[2],6); memcpy(buf,dtlsseq,8); } else { memcpy(buf,seq,8); for (i=7; i>=0; i--) /* increment */ { ++seq[i]; if (seq[i] != 0) break; } } buf[8]=rec->type; buf[9]=(unsigned char)(s->version>>8); buf[10]=(unsigned char)(s->version); buf[11]=rec->length>>8; buf[12]=rec->length&0xff; pad=EVP_CIPHER_CTX_ctrl(ds,EVP_CTRL_AEAD_TLS1_AAD,13,buf); if (send) { l+=pad; rec->length+=pad; } } else if ((bs != 1) && send)
int PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen, ASN1_TYPE *param, const EVP_CIPHER *c, const EVP_MD *md, int en_de) { unsigned char *salt, key[EVP_MAX_KEY_LENGTH]; int saltlen, iter; int rv = 0; unsigned int keylen = 0; int prf_nid, hmac_md_nid; PBKDF2PARAM *kdf = NULL; const EVP_MD *prfmd; if (EVP_CIPHER_CTX_cipher(ctx) == NULL) { EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_NO_CIPHER_SET); goto err; } keylen = EVP_CIPHER_CTX_key_length(ctx); OPENSSL_assert(keylen <= sizeof(key)); /* Decode parameter */ kdf = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(PBKDF2PARAM), param); if (kdf == NULL) { EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_DECODE_ERROR); goto err; } keylen = EVP_CIPHER_CTX_key_length(ctx); /* Now check the parameters of the kdf */ if (kdf->keylength && (ASN1_INTEGER_get(kdf->keylength) != (int)keylen)) { EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_UNSUPPORTED_KEYLENGTH); goto err; } if (kdf->prf) prf_nid = OBJ_obj2nid(kdf->prf->algorithm); else prf_nid = NID_hmacWithSHA1; if (!EVP_PBE_find(EVP_PBE_TYPE_PRF, prf_nid, NULL, &hmac_md_nid, 0)) { EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_UNSUPPORTED_PRF); goto err; } prfmd = EVP_get_digestbynid(hmac_md_nid); if (prfmd == NULL) { EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_UNSUPPORTED_PRF); goto err; } if (kdf->salt->type != V_ASN1_OCTET_STRING) { EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_UNSUPPORTED_SALT_TYPE); goto err; } /* it seems that its all OK */ salt = kdf->salt->value.octet_string->data; saltlen = kdf->salt->value.octet_string->length; iter = ASN1_INTEGER_get(kdf->iter); if (!PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, iter, prfmd, keylen, key)) goto err; rv = EVP_CipherInit_ex(ctx, NULL, NULL, key, NULL, en_de); err: OPENSSL_cleanse(key, keylen); PBKDF2PARAM_free(kdf); return rv; }
static int ssl_decrypt_record( dssl_decoder_stack* stack, u_char* data, uint32_t len, u_char** out, uint32_t* out_len, int *buffer_aquired ) { u_char* buf = NULL; uint32_t buf_len = len; int rc = DSSL_RC_OK; int block_size; const EVP_CIPHER* c = NULL; _ASSERT( stack ); _ASSERT( stack->sess ); _ASSERT( stack->cipher ); rc = ssls_get_decrypt_buffer( stack->sess, &buf, buf_len ); if( rc != DSSL_RC_OK ) return rc; *buffer_aquired = 1; c = EVP_CIPHER_CTX_cipher( stack->cipher ); block_size = EVP_CIPHER_block_size( c ); DEBUG_TRACE3( "using cipher %s (mode=%u, block=%u)\n", EVP_CIPHER_name(c), stack->sess->cipher_mode, block_size ); if( block_size != 1 ) { if( len == 0 || (len % block_size) != 0 ) { return NM_ERROR( DSSL_E_SSL_DECRYPTION_ERROR ); } } DEBUG_TRACE_BUF("encrypted", data, len); if ( EVP_CIPH_GCM_MODE == stack->sess->cipher_mode || EVP_CIPH_CCM_MODE == stack->sess->cipher_mode ) { if ( len < EVP_GCM_TLS_EXPLICIT_IV_LEN ) { return NM_ERROR( DSSL_E_SSL_DECRYPTION_ERROR ); } if ( EVP_CIPH_GCM_MODE == stack->sess->cipher_mode ) { /* set 'explicit_nonce' part from message bytes */ rc = EVP_CIPHER_CTX_ctrl(stack->cipher, EVP_CTRL_GCM_SET_IV_INV, EVP_GCM_TLS_EXPLICIT_IV_LEN, data); } else { /* 4 bytes write_iv, 8 bytes explicit_nonce, 4 bytes counter */ u_char ccm_nonce[EVP_GCM_TLS_TAG_LEN] = { 0 }; rc = EVP_CIPHER_CTX_ctrl(stack->cipher, EVP_CTRL_CCM_GET_TAG, sizeof(ccm_nonce), ccm_nonce); if( rc != DSSL_RC_OK ) return rc; /* overwrite exlicit_nonce part with packet data */ memcpy(ccm_nonce + 1 + EVP_GCM_TLS_FIXED_IV_LEN, data, EVP_GCM_TLS_EXPLICIT_IV_LEN); rc = EVP_CIPHER_CTX_ctrl(stack->cipher, EVP_CTRL_CCM_SET_TAG, sizeof(ccm_nonce), ccm_nonce); if( rc != DSSL_RC_OK ) return rc; } data += EVP_GCM_TLS_EXPLICIT_IV_LEN; len -= EVP_GCM_TLS_EXPLICIT_IV_LEN; } rc = EVP_Cipher(stack->cipher, buf, data, len ); buf_len = len; /* strip the padding */ if( block_size != 1 ) { if( buf[len-1] >= buf_len - 1 ) return NM_ERROR( DSSL_E_SSL_DECRYPTION_ERROR ); buf_len -= buf[len-1] + 1; } DEBUG_TRACE_BUF("decrypted", buf, buf_len); /* ignore auth tag, which is 16 (for CCM/GCM) or 8 (for CCM-8) bytes */ if ( EVP_CIPH_GCM_MODE == stack->sess->cipher_mode || EVP_CIPH_CCM_MODE == stack->sess->cipher_mode ) { if (NULL == stack->sess->dssl_cipher_suite->extra_info) buf_len -= EVP_GCM_TLS_TAG_LEN; else buf_len -= (size_t)stack->sess->dssl_cipher_suite->extra_info; } *out = buf; *out_len = buf_len; return DSSL_RC_OK; }
/* dtls1_enc encrypts/decrypts the record in |s->wrec| / |s->rrec|, respectively. * * Returns: * 0: (in non-constant time) if the record is publically invalid (i.e. too * short etc). * 1: if the record's padding is valid / the encryption was successful. * -1: if the record's padding/AEAD-authenticator is invalid or, if sending, * an internal error occured. */ int dtls1_enc(SSL *s, int send) { SSL3_RECORD *rec; EVP_CIPHER_CTX *ds; unsigned long l; int bs, i, j, k, mac_size = 0; const EVP_CIPHER *enc; if (send) { if (EVP_MD_CTX_md(s->write_hash)) { mac_size = EVP_MD_CTX_size(s->write_hash); if (mac_size < 0) return -1; } ds = s->enc_write_ctx; rec = &(s->s3->wrec); if (s->enc_write_ctx == NULL) enc = NULL; else { enc = EVP_CIPHER_CTX_cipher(s->enc_write_ctx); if (rec->data != rec->input) /* we can't write into the input stream */ fprintf(stderr, "%s:%d: rec->data != rec->input\n", __FILE__, __LINE__); else if (EVP_CIPHER_block_size(ds->cipher) > 1) { arc4random_buf(rec->input, EVP_CIPHER_block_size(ds->cipher)); } } } else { if (EVP_MD_CTX_md(s->read_hash)) { mac_size = EVP_MD_CTX_size(s->read_hash); OPENSSL_assert(mac_size >= 0); } ds = s->enc_read_ctx; rec = &(s->s3->rrec); if (s->enc_read_ctx == NULL) enc = NULL; else enc = EVP_CIPHER_CTX_cipher(s->enc_read_ctx); } if ((s->session == NULL) || (ds == NULL) || (enc == NULL)) { memmove(rec->data, rec->input, rec->length); rec->input = rec->data; } else { l = rec->length; bs = EVP_CIPHER_block_size(ds->cipher); if ((bs != 1) && send) { i = bs - ((int)l % bs); /* Add weird padding of upto 256 bytes */ /* we need to add 'i' padding bytes of value j */ j = i - 1; if (s->options & SSL_OP_TLS_BLOCK_PADDING_BUG) { if (s->s3->flags & TLS1_FLAGS_TLS_PADDING_BUG) j++; } for (k = (int)l; k < (int)(l + i); k++) rec->input[k] = j; l += i; rec->length += i; } if (!send) { if (l == 0 || l % bs != 0) return 0; } EVP_Cipher(ds, rec->data, rec->input, l); if ((bs != 1) && !send) return tls1_cbc_remove_padding(s, rec, bs, mac_size); } return (1); }
int PKCS5_v2_scrypt_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen, ASN1_TYPE *param, const EVP_CIPHER *c, const EVP_MD *md, int en_de) { unsigned char *salt, key[EVP_MAX_KEY_LENGTH]; uint64_t p, r, N; size_t saltlen; size_t keylen = 0; int rv = 0; SCRYPT_PARAMS *sparam = NULL; if (EVP_CIPHER_CTX_cipher(ctx) == NULL) { EVPerr(EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN, EVP_R_NO_CIPHER_SET); goto err; } /* Decode parameter */ sparam = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(SCRYPT_PARAMS), param); if (sparam == NULL) { EVPerr(EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN, EVP_R_DECODE_ERROR); goto err; } keylen = EVP_CIPHER_CTX_key_length(ctx); /* Now check the parameters of sparam */ if (sparam->keyLength) { uint64_t spkeylen; if ((ASN1_INTEGER_get_uint64(&spkeylen, sparam->keyLength) == 0) || (spkeylen != keylen)) { EVPerr(EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN, EVP_R_UNSUPPORTED_KEYLENGTH); goto err; } } /* Check all parameters fit in uint64_t and are acceptable to scrypt */ if (ASN1_INTEGER_get_uint64(&N, sparam->costParameter) == 0 || ASN1_INTEGER_get_uint64(&r, sparam->blockSize) == 0 || ASN1_INTEGER_get_uint64(&p, sparam->parallelizationParameter) == 0 || EVP_PBE_scrypt(NULL, 0, NULL, 0, N, r, p, 0, NULL, 0) == 0) { EVPerr(EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN, EVP_R_ILLEGAL_SCRYPT_PARAMETERS); goto err; } /* it seems that its all OK */ salt = sparam->salt->data; saltlen = sparam->salt->length; if (EVP_PBE_scrypt(pass, passlen, salt, saltlen, N, r, p, 0, key, keylen) == 0) goto err; rv = EVP_CipherInit_ex(ctx, NULL, NULL, key, NULL, en_de); err: if (keylen) OPENSSL_cleanse(key, keylen); SCRYPT_PARAMS_free(sparam); return rv; }
/* ssl3_enc encrypts/decrypts the record in |s->wrec| / |s->rrec|, respectively. * * Returns: * 0: (in non-constant time) if the record is publically invalid (i.e. too * short etc). * 1: if the record's padding is valid / the encryption was successful. * -1: if the record's padding is invalid or, if sending, an internal error * occurred. */ int ssl3_enc(SSL *s, int send) { SSL3_RECORD *rec; EVP_CIPHER_CTX *ds; unsigned long l; int bs,i,mac_size=0; const EVP_CIPHER *enc; if (send) { ds=s->enc_write_ctx; rec= &(s->s3->wrec); if (s->enc_write_ctx == NULL) enc=NULL; else enc=EVP_CIPHER_CTX_cipher(s->enc_write_ctx); } else { ds=s->enc_read_ctx; rec= &(s->s3->rrec); if (s->enc_read_ctx == NULL) enc=NULL; else enc=EVP_CIPHER_CTX_cipher(s->enc_read_ctx); } if ((s->session == NULL) || (ds == NULL) || (enc == NULL)) { memmove(rec->data,rec->input,rec->length); rec->input=rec->data; } else { l=rec->length; bs=EVP_CIPHER_block_size(ds->cipher); /* COMPRESS */ if ((bs != 1) && send) { i=bs-((int)l%bs); /* we need to add 'i-1' padding bytes */ l+=i; /* the last of these zero bytes will be overwritten * with the padding length. */ memset(&rec->input[rec->length], 0, i); rec->length+=i; rec->input[l-1]=(i-1); } if (!send) { if (l == 0 || l%bs != 0) return 0; /* otherwise, rec->length >= bs */ } EVP_Cipher(ds,rec->data,rec->input,l); if (EVP_MD_CTX_md(s->read_hash) != NULL) mac_size = EVP_MD_CTX_size(s->read_hash); if ((bs != 1) && !send) return ssl3_cbc_remove_padding(s, rec, bs, mac_size); } return(1); }
const cipher_kt_t * cipher_ctx_get_cipher_kt(const cipher_ctx_t *ctx) { return ctx ? EVP_CIPHER_CTX_cipher(ctx) : NULL; }
const cipher_kt_t * cipher_ctx_get_cipher_kt (const cipher_ctx_t *ctx) { return EVP_CIPHER_CTX_cipher(ctx); }
/* This equivalent functionality was submitted for OpenSSL 1.1.1+ in * https://github.com/openssl/openssl/pull/1666 */ static int dtls_get_data_mtu(struct openconnect_info *vpninfo, int mtu) { int ivlen, maclen, blocksize = 0, pad = 0; #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) const SSL_CIPHER *s_ciph = SSL_get_current_cipher(vpninfo->dtls_ssl); int cipher_nid; const EVP_CIPHER *e_ciph; const EVP_MD *e_md; char wtf[128]; cipher_nid = SSL_CIPHER_get_cipher_nid(s_ciph); if (cipher_nid == NID_chacha20_poly1305) { ivlen = 0; /* Automatically derived from handshake and seqno */ maclen = 16; /* Poly1305 */ } else { e_ciph = EVP_get_cipherbynid(cipher_nid); switch (EVP_CIPHER_mode(e_ciph)) { case EVP_CIPH_GCM_MODE: ivlen = EVP_GCM_TLS_EXPLICIT_IV_LEN; maclen = EVP_GCM_TLS_TAG_LEN; break; case EVP_CIPH_CCM_MODE: ivlen = EVP_CCM_TLS_EXPLICIT_IV_LEN; SSL_CIPHER_description(s_ciph, wtf, sizeof(wtf)); if (strstr(wtf, "CCM8")) maclen = 8; else maclen = 16; break; case EVP_CIPH_CBC_MODE: blocksize = EVP_CIPHER_block_size(e_ciph); ivlen = EVP_CIPHER_iv_length(e_ciph); pad = 1; e_md = EVP_get_digestbynid(SSL_CIPHER_get_digest_nid(s_ciph)); maclen = EVP_MD_size(e_md); break; default: vpn_progress(vpninfo, PRG_ERR, _("Unable to calculate DTLS overhead for %s\n"), SSL_CIPHER_get_name(s_ciph)); ivlen = 0; maclen = DTLS_OVERHEAD; break; } } #else /* OpenSSL <= 1.0.2 only supports CBC ciphers with PSK */ ivlen = EVP_CIPHER_iv_length(EVP_CIPHER_CTX_cipher(vpninfo->dtls_ssl->enc_read_ctx)); maclen = EVP_MD_CTX_size(vpninfo->dtls_ssl->read_hash); blocksize = ivlen; pad = 1; #endif /* Even when it pretended to, OpenSSL never did encrypt-then-mac. * So the MAC is *inside* the encryption, unconditionally. * https://github.com/openssl/openssl/pull/1705 */ if (mtu < DTLS1_RT_HEADER_LENGTH + ivlen) return 0; mtu -= DTLS1_RT_HEADER_LENGTH + ivlen; /* For CBC mode round down to blocksize */ if (blocksize) mtu -= mtu % blocksize; /* Finally, CBC modes require at least one byte to indicate * padding length, as well as the MAC. */ if (mtu < pad + maclen) return 0; mtu -= pad + maclen; return mtu; }