Control: tags 828371 + patch Control: tags 828371 + pending Dear maintainer,
I've prepared an NMU for lastpass-cli (versioned as 1.0.0-1.1) and uploaded it to DELAYED/4. Please feel free to tell me if I should delay it longer. Regards. Sebastian
diff -Nru lastpass-cli-1.0.0/debian/changelog lastpass-cli-1.0.0/debian/changelog --- lastpass-cli-1.0.0/debian/changelog 2016-10-20 16:17:08.000000000 +0200 +++ lastpass-cli-1.0.0/debian/changelog 2016-12-06 21:10:47.000000000 +0100 @@ -1,3 +1,10 @@ +lastpass-cli (1.0.0-1.1) unstable; urgency=medium + + * Non-maintainer upload. + * Get it built against openssl 1.1.0 (Closes: #828371). + + -- Sebastian Andrzej Siewior <sebast...@breakpoint.cc> Tue, 06 Dec 2016 21:10:47 +0100 + lastpass-cli (1.0.0-1) unstable; urgency=medium * New upstream 1.0.0 diff -Nru lastpass-cli-1.0.0/debian/patches/0001-cipher-support-opaque-EVP_CIPHER_CTX.patch lastpass-cli-1.0.0/debian/patches/0001-cipher-support-opaque-EVP_CIPHER_CTX.patch --- lastpass-cli-1.0.0/debian/patches/0001-cipher-support-opaque-EVP_CIPHER_CTX.patch 1970-01-01 01:00:00.000000000 +0100 +++ lastpass-cli-1.0.0/debian/patches/0001-cipher-support-opaque-EVP_CIPHER_CTX.patch 2016-12-06 21:09:03.000000000 +0100 @@ -0,0 +1,214 @@ +From 6e4ff62df789b55b80c14b2e7b15c25154fbf9fe Mon Sep 17 00:00:00 2001 +From: Bob Copeland <copel...@lastpass.com> +Date: Mon, 5 Dec 2016 09:55:19 -0500 +Subject: [PATCH 1/3] cipher: support opaque EVP_CIPHER_CTX + +In OpenSSL 1.1+, EVP_CIPHER_CTX can no longer be declared on +the stack; instead you have to declare a pointer and then +use _new()/_free() to allocate or free it. These functions +continue to work on older OpenSSL, so switch to the new +method. + +Signed-off-by: Bob Copeland <copel...@lastpass.com> +--- + cipher.c | 36 +++++++++++++++++++++--------------- + config.c | 33 +++++++++++++++++++-------------- + 2 files changed, 40 insertions(+), 29 deletions(-) + +diff --git a/cipher.c b/cipher.c +index 71487787af5a..ebae92e0431c 100644 +--- a/cipher.c ++++ b/cipher.c +@@ -147,36 +147,39 @@ int cipher_rsa_encrypt(const char *plaintext, + + char *cipher_aes_decrypt(const unsigned char *ciphertext, size_t len, const unsigned char key[KDF_HASH_LEN]) + { +- EVP_CIPHER_CTX ctx; ++ EVP_CIPHER_CTX *ctx; + char *plaintext; + int out_len; + + if (!len) + return NULL; + +- EVP_CIPHER_CTX_init(&ctx); ++ ctx = EVP_CIPHER_CTX_new(); ++ if (!ctx) ++ return NULL; ++ + plaintext = xcalloc(len + AES_BLOCK_SIZE + 1, 1); + if (len >= 33 && len % 16 == 1 && ciphertext[0] == '!') { +- if (!EVP_DecryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, key, (unsigned char *)(ciphertext + 1))) ++ if (!EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, (unsigned char *)(ciphertext + 1))) + goto error; + ciphertext += 17; + len -= 17; + } else { +- if (!EVP_DecryptInit_ex(&ctx, EVP_aes_256_ecb(), NULL, key, NULL)) ++ if (!EVP_DecryptInit_ex(ctx, EVP_aes_256_ecb(), NULL, key, NULL)) + goto error; + } +- if (!EVP_DecryptUpdate(&ctx, (unsigned char *)plaintext, &out_len, (unsigned char *)ciphertext, len)) ++ if (!EVP_DecryptUpdate(ctx, (unsigned char *)plaintext, &out_len, (unsigned char *)ciphertext, len)) + goto error; + len = out_len; +- if (!EVP_DecryptFinal_ex(&ctx, (unsigned char *)(plaintext + out_len), &out_len)) ++ if (!EVP_DecryptFinal_ex(ctx, (unsigned char *)(plaintext + out_len), &out_len)) + goto error; + len += out_len; + plaintext[len] = '\0'; +- EVP_CIPHER_CTX_cleanup(&ctx); ++ EVP_CIPHER_CTX_free(ctx); + return plaintext; + + error: +- EVP_CIPHER_CTX_cleanup(&ctx); ++ EVP_CIPHER_CTX_free(ctx); + secure_clear(plaintext, len + AES_BLOCK_SIZE + 1); + free(plaintext); + return NULL; +@@ -188,7 +191,7 @@ size_t cipher_aes_encrypt_bytes(const unsigned char *bytes, size_t len, + const unsigned char *iv, + unsigned char **out) + { +- EVP_CIPHER_CTX ctx; ++ EVP_CIPHER_CTX *ctx; + int out_len; + size_t ret_len = 0; + unsigned char *ctext; +@@ -197,24 +200,27 @@ size_t cipher_aes_encrypt_bytes(const unsigned char *bytes, size_t len, + if (!ctext) + ctext = xcalloc(len + AES_BLOCK_SIZE * 2 + 1, 1); + +- EVP_CIPHER_CTX_init(&ctx); +- if (!EVP_EncryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, key, iv)) ++ ctx = EVP_CIPHER_CTX_new(); ++ if (!ctx) + goto error; + +- if (!EVP_EncryptUpdate(&ctx, ctext, &out_len, bytes, len)) ++ if (!EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv)) ++ goto error; ++ ++ if (!EVP_EncryptUpdate(ctx, ctext, &out_len, bytes, len)) + goto error; + + ret_len += out_len; +- if (!EVP_EncryptFinal_ex(&ctx, ctext + ret_len, &out_len)) ++ if (!EVP_EncryptFinal_ex(ctx, ctext + ret_len, &out_len)) + goto error; + ret_len += out_len; + +- EVP_CIPHER_CTX_cleanup(&ctx); ++ EVP_CIPHER_CTX_free(ctx); + *out = ctext; + return ret_len; + + error: +- EVP_CIPHER_CTX_cleanup(&ctx); ++ EVP_CIPHER_CTX_free(ctx); + if (!*out) + free(ctext); + die("Failed to encrypt data."); +diff --git a/config.c b/config.c +index bd68cfe8b21b..976202c5d6ad 100644 +--- a/config.c ++++ b/config.c +@@ -319,7 +319,7 @@ size_t config_read_buffer(const char *name, unsigned char **out) + + static size_t encrypt_buffer(const char *buffer, size_t in_len, unsigned const char key[KDF_HASH_LEN], char **out) + { +- EVP_CIPHER_CTX ctx; ++ EVP_CIPHER_CTX *ctx; + char *ciphertext; + unsigned char iv[AES_BLOCK_SIZE]; + int out_len; +@@ -329,31 +329,34 @@ static size_t encrypt_buffer(const char *buffer, size_t in_len, unsigned const c + if (!RAND_bytes(iv, AES_BLOCK_SIZE)) + die("Could not generate random bytes for CBC IV."); + +- EVP_CIPHER_CTX_init(&ctx); + ciphertext = xcalloc(in_len + AES_BLOCK_SIZE * 2 + SHA256_DIGEST_LENGTH, 1); + ++ ctx = EVP_CIPHER_CTX_new(); ++ if (!ctx) ++ goto error; ++ + len = SHA256_DIGEST_LENGTH; + memcpy(ciphertext + len, iv, AES_BLOCK_SIZE); + len += AES_BLOCK_SIZE; + +- if (!EVP_EncryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, key, iv)) ++ if (!EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv)) + goto error; +- if (!EVP_EncryptUpdate(&ctx, (unsigned char *)(ciphertext + len), &out_len, (unsigned char *)buffer, in_len)) ++ if (!EVP_EncryptUpdate(ctx, (unsigned char *)(ciphertext + len), &out_len, (unsigned char *)buffer, in_len)) + goto error; + len += out_len; +- if (!EVP_EncryptFinal_ex(&ctx, (unsigned char *)(ciphertext + len), &out_len)) ++ if (!EVP_EncryptFinal_ex(ctx, (unsigned char *)(ciphertext + len), &out_len)) + goto error; + len += out_len; +- EVP_CIPHER_CTX_cleanup(&ctx); + + if (!HMAC(EVP_sha256(), key, KDF_HASH_LEN, (unsigned char *)(ciphertext + SHA256_DIGEST_LENGTH), len - SHA256_DIGEST_LENGTH, (unsigned char *)ciphertext, &hmac_len)) + goto error; + ++ EVP_CIPHER_CTX_free(ctx); + *out = ciphertext; + return len; + + error: +- EVP_CIPHER_CTX_cleanup(&ctx); ++ EVP_CIPHER_CTX_free(ctx); + free(ciphertext); + die("Failed to encrypt data."); + +@@ -361,14 +364,16 @@ static size_t encrypt_buffer(const char *buffer, size_t in_len, unsigned const c + + static size_t decrypt_buffer(const unsigned char *buffer, size_t in_len, unsigned const char key[KDF_HASH_LEN], unsigned char **out) + { +- EVP_CIPHER_CTX ctx; ++ EVP_CIPHER_CTX *ctx; + unsigned char *plaintext = NULL; + int out_len; + unsigned int hmac_len; + size_t len; + unsigned char hmac[SHA256_DIGEST_LENGTH]; + +- EVP_CIPHER_CTX_init(&ctx); ++ ctx = EVP_CIPHER_CTX_new(); ++ if (!ctx) ++ goto error; + + if (in_len < (SHA256_DIGEST_LENGTH + AES_BLOCK_SIZE * 2)) + goto error; +@@ -379,20 +384,20 @@ static size_t decrypt_buffer(const unsigned char *buffer, size_t in_len, unsigne + goto error; + + plaintext = xcalloc(in_len + AES_BLOCK_SIZE, 1); +- if (!EVP_DecryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, key, (unsigned char *)(buffer + SHA256_DIGEST_LENGTH))) ++ if (!EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, (unsigned char *)(buffer + SHA256_DIGEST_LENGTH))) + goto error; +- if (!EVP_DecryptUpdate(&ctx, (unsigned char *)plaintext, &out_len, (unsigned char *)(buffer + SHA256_DIGEST_LENGTH + AES_BLOCK_SIZE), in_len - SHA256_DIGEST_LENGTH - AES_BLOCK_SIZE)) ++ if (!EVP_DecryptUpdate(ctx, (unsigned char *)plaintext, &out_len, (unsigned char *)(buffer + SHA256_DIGEST_LENGTH + AES_BLOCK_SIZE), in_len - SHA256_DIGEST_LENGTH - AES_BLOCK_SIZE)) + goto error; + len = out_len; +- if (!EVP_DecryptFinal_ex(&ctx, (unsigned char *)(plaintext + out_len), &out_len)) ++ if (!EVP_DecryptFinal_ex(ctx, (unsigned char *)(plaintext + out_len), &out_len)) + goto error; + len += out_len; +- EVP_CIPHER_CTX_cleanup(&ctx); ++ EVP_CIPHER_CTX_free(ctx); + *out = plaintext; + return len; + + error: +- EVP_CIPHER_CTX_cleanup(&ctx); ++ EVP_CIPHER_CTX_free(ctx); + free(plaintext); + *out = NULL; + return 0; +-- +2.11.0 + diff -Nru lastpass-cli-1.0.0/debian/patches/0002-cipher-drop-p8inf-broken-flag-check.patch lastpass-cli-1.0.0/debian/patches/0002-cipher-drop-p8inf-broken-flag-check.patch --- lastpass-cli-1.0.0/debian/patches/0002-cipher-drop-p8inf-broken-flag-check.patch 1970-01-01 01:00:00.000000000 +0100 +++ lastpass-cli-1.0.0/debian/patches/0002-cipher-drop-p8inf-broken-flag-check.patch 2016-12-06 21:09:03.000000000 +0100 @@ -0,0 +1,37 @@ +From 390c01a8111a4f2fc5b2abb3691c4a0238365922 Mon Sep 17 00:00:00 2001 +From: Bob Copeland <m...@bobcopeland.com> +Date: Mon, 5 Dec 2016 09:58:07 -0500 +Subject: [PATCH 2/3] cipher: drop p8inf->broken flag check +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +struct pkcs8_priv_key_info_st is now opaque as of OpenSSL 1.1 +so we cannot look directly at its flags going forward. + +./cipher.c: In function ‘cipher_rsa_decrypt’: ./cipher.c:73:11: error: dereferencing pointer to incomplete type ‘PKCS8_PRIV_KEY_INFO {aka struct +pkcs8_priv_key_info_st}’ + if (p8inf->broken) + ^ + +Signed-off-by: Bob Copeland <copel...@lastpass.com> +--- + cipher.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/cipher.c b/cipher.c +index ebae92e0431c..86d19eead546 100644 +--- a/cipher.c ++++ b/cipher.c +@@ -70,8 +70,6 @@ char *cipher_rsa_decrypt(const unsigned char *ciphertext, size_t len, const stru + pkey = EVP_PKCS82PKEY(p8inf); + if (!pkey) + goto out; +- if (p8inf->broken) +- goto out; + rsa = EVP_PKEY_get1_RSA(pkey); + if (!rsa) + goto out; +-- +2.11.0 + diff -Nru lastpass-cli-1.0.0/debian/patches/0003-pbkdf2-support-openssl-1.1.patch lastpass-cli-1.0.0/debian/patches/0003-pbkdf2-support-openssl-1.1.patch --- lastpass-cli-1.0.0/debian/patches/0003-pbkdf2-support-openssl-1.1.patch 1970-01-01 01:00:00.000000000 +0100 +++ lastpass-cli-1.0.0/debian/patches/0003-pbkdf2-support-openssl-1.1.patch 2016-12-06 21:09:03.000000000 +0100 @@ -0,0 +1,93 @@ +From 0f9e3d940fa2abee3f7dcedceec192e45e471bc6 Mon Sep 17 00:00:00 2001 +From: Bob Copeland <m...@bobcopeland.com> +Date: Mon, 5 Dec 2016 10:55:49 -0500 +Subject: [PATCH 3/3] pbkdf2: support openssl 1.1+ + +In OpenSSL 1.1, HMAC_CTX is now opaque and _init/_cleanup functions +are history. Change the pbkdf2 implementation to conditionally +use HMAX_CTX_new()/_free() and use context pointers throughout. + +Signed-off-by: Bob Copeland <copel...@lastpass.com> +--- + pbkdf2.c | 36 +++++++++++++++++++++++++----------- + 1 file changed, 25 insertions(+), 11 deletions(-) + +diff --git a/pbkdf2.c b/pbkdf2.c +index f3c763420bbc..de15bae0d430 100644 +--- a/pbkdf2.c ++++ b/pbkdf2.c +@@ -1,5 +1,6 @@ + /* + * Copyright (c) 2014-2016 Thomas Hurst. ++ * Copyright (c) 2016 LastPass. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal +@@ -40,7 +41,7 @@ int fallback_pkcs5_pbkdf2_hmac(const char *pass, size_t pass_len, + const unsigned char *salt, size_t salt_len, unsigned int iterations, + const EVP_MD *digest, size_t key_len, unsigned char *output) + { +- HMAC_CTX ctx; ++ HMAC_CTX *ctx; + unsigned char *out = output; + unsigned int iter = 1, count = 1; + unsigned int cp_len, i, ret = 0; +@@ -52,8 +53,17 @@ int fallback_pkcs5_pbkdf2_hmac(const char *pass, size_t pass_len, + + unsigned char tmp_md[md_len]; + +- HMAC_CTX_init(&ctx); +- ERR_IFZERO(HMAC_Init_ex(&ctx, pass, pass_len, digest, NULL)); ++#if OPENSSL_VERSION_NUMBER < 0x10100000L ++ HMAC_CTX real_ctx; ++ ctx = &real_ctx; ++ HMAC_CTX_init(ctx); ++#else ++ ctx = HMAC_CTX_new(); ++ if (!ctx) ++ return 0; ++#endif ++ ++ ERR_IFZERO(HMAC_Init_ex(ctx, pass, pass_len, digest, NULL)); + + while (key_left) { + cp_len = min(key_left, md_len); +@@ -64,16 +74,16 @@ int fallback_pkcs5_pbkdf2_hmac(const char *pass, size_t pass_len, + c[2] = (count >> 8) & 0xff; + c[3] = (count) & 0xff; + +- ERR_IFZERO(HMAC_Init_ex(&ctx, NULL, 0, digest, NULL)); +- ERR_IFZERO(HMAC_Update(&ctx, salt, salt_len)); +- ERR_IFZERO(HMAC_Update(&ctx, c, 4)); +- ERR_IFZERO(HMAC_Final(&ctx, tmp_md, NULL)); ++ ERR_IFZERO(HMAC_Init_ex(ctx, NULL, 0, digest, NULL)); ++ ERR_IFZERO(HMAC_Update(ctx, salt, salt_len)); ++ ERR_IFZERO(HMAC_Update(ctx, c, 4)); ++ ERR_IFZERO(HMAC_Final(ctx, tmp_md, NULL)); + memcpy(out, tmp_md, cp_len); + + for (iter=1; iter < iterations; iter++) { +- ERR_IFZERO(HMAC_Init_ex(&ctx, NULL, 0, digest, NULL)); +- ERR_IFZERO(HMAC_Update(&ctx, tmp_md, md_len)); +- ERR_IFZERO(HMAC_Final(&ctx, tmp_md, NULL)); ++ ERR_IFZERO(HMAC_Init_ex(ctx, NULL, 0, digest, NULL)); ++ ERR_IFZERO(HMAC_Update(ctx, tmp_md, md_len)); ++ ERR_IFZERO(HMAC_Final(ctx, tmp_md, NULL)); + + for (i = 0; i < cp_len; i++) { + out[i] ^= tmp_md[i]; +@@ -87,6 +97,10 @@ int fallback_pkcs5_pbkdf2_hmac(const char *pass, size_t pass_len, + ret = 1; + + ERR_LABEL +- HMAC_CTX_cleanup(&ctx); ++#if OPENSSL_VERSION_NUMBER < 0x10100000L ++ HMAC_CTX_cleanup(ctx); ++#else ++ HMAC_CTX_free(ctx); ++#endif + return ret; + } +-- +2.11.0 + diff -Nru lastpass-cli-1.0.0/debian/patches/series lastpass-cli-1.0.0/debian/patches/series --- lastpass-cli-1.0.0/debian/patches/series 2016-10-20 16:16:48.000000000 +0200 +++ lastpass-cli-1.0.0/debian/patches/series 2016-12-06 21:10:47.000000000 +0100 @@ -1 +1,4 @@ 01_build_manpage +0001-cipher-support-opaque-EVP_CIPHER_CTX.patch +0002-cipher-drop-p8inf-broken-flag-check.patch +0003-pbkdf2-support-openssl-1.1.patch