发表文章

[C++] 将 RSA-PSS 操作传递给令牌 * 当它支持它 * Pass RSA-PSS operation to the token *when it supports it*[libp11]

mouse07410 2017-10-9 92

这不是一个 bug 报告 (至少我不认为它是一个 bug)。MacOS 山脉 10.12.6, Xcode-8.3.3。

当前 Github 版本的 libp11 , p11-kit v0.23.2。

我有一个 USB PKCS#11 设备, 目前无法由 OpenSC opensc-pkcs11.so 服务。

我的系统已安装 p11-kit 。为该设备提供服务的库是 /usr/local/lib/yubihsm_pkcs11.so

请帮助我配置 p11-kitlibp11 或 OpenSSL, 以便 libp11 在请求时使用上述库。

谢谢!

@nmav也许你也可以介入?

原文:

This is not a bug report (at least I don't think it's a bug). MacOS Sierra 10.12.6, Xcode-8.3.3.

Current Github version of libp11, p11-kit v0.23.2.

I have a USB PKCS#11 device that currently cannot be served by OpenSC opensc-pkcs11.so.

My system has p11-kit installed. The library that serves this device is /usr/local/lib/yubihsm_pkcs11.so.

Could you please help me configuring p11-kit or libp11 or OpenSSL so that libp11 would use the above library upon request?

Thank you!

@nmav perhaps you could step in too?

相关推荐
最新评论 (111)
nmav 2017-10-9
1

很可能你只需要注册 yubihsm_pkcs11. p11-kit。
请参见https://p11-glue.freedesktop.org/doc/p11-kit/config-example.html

原文:

Most likely you only need to register yubihsm_pkcs11.so with p11-kit.
See https://p11-glue.freedesktop.org/doc/p11-kit/config-example.html

mouse07410 2017-10-9
2

很可能你只需要注册 yubihsm_pkcs11. p11-kit。

@nmav谢谢!但看起来我需要做更多的事情。我知道这个模块不应该 "预先" 初始化。将此模块添加到 OpenSSL 的自述文件说添加 "init = 0"。有什么方法可以对 p11-kit 吗?

$ p11-kit list-modules
yubihsm_pkcs11: Error opening configuration file '(null)'
p11-kit: yhsm2: module failed to initialize, skipping: The operation failed
p11-kit-trust: p11-kit-trust.so
    library-description: PKCS#11 Kit Trust Module
    library-manufacturer: PKCS#11 Kit
    library-version: 0.23
    token: Default Trust
        manufacturer: PKCS#11 Kit
        model: p11-kit-trust
        serial-number: 1
        hardware-version: 0.23
        flags:
               write-protected
               token-initialized
    token: System Trust
        manufacturer: PKCS#11 Kit
        model: p11-kit-trust
        serial-number: 1
        hardware-version: 0.23
        flags:
               write-protected
               token-initialized
pkcs11: /Library/OpenSC/lib/opensc-pkcs11.dylib
    library-description: OpenSC smartcard framework
    library-manufacturer: OpenSC Project
    library-version: 0.17
softhsm: /opt/local/lib/softhsm/libsofthsm2.dylib
    library-description: Implementation of PKCS11
    library-manufacturer: SoftHSM
    library-version: 2.3
    token: Botan PKCS#11 tests
        manufacturer: SoftHSM project
        model: SoftHSM v2
        serial-number: b158018a21bc4979
        hardware-version: 2.3
        firmware-version: 2.3
        flags:
               rng
               login-required
               user-pin-initialized
               restore-key-not-needed
               token-initialized
    token: test
        manufacturer: SoftHSM project
        model: SoftHSM v2
        serial-number: 02b891b82879828e
        hardware-version: 2.3
        firmware-version: 2.3
        flags:
               rng
               login-required
               user-pin-initialized
               restore-key-not-needed
               token-initialized
    token: 
        manufacturer: SoftHSM project
        model: SoftHSM v2
        serial-number: 
        hardware-version: 2.3
        firmware-version: 2.3
        flags:
               rng
               login-required
               restore-key-not-needed
               so-pin-locked
               so-pin-to-be-changed
ykcs11: /usr/local/lib/libykcs11.dylib
    library-description: PKCS#11 PIV Library (SP-800-73)
    library-manufacturer: Yubico (www.yubico.com)
    library-version: 1.44
$ cat ~/.config/pkcs11/modules/yhsm2.module 
module: /usr/local/lib/yubihsm_pkcs11.dylib
$
原文:

Most likely you only need to register yubihsm_pkcs11.so with p11-kit.

@nmav thank you! But it looks like I need to do more. I know that this module should not be initialized "in advance". The README for adding this module to OpenSSL said to add "init = 0". Is there any way to do the same with p11-kit?

$ p11-kit list-modules
yubihsm_pkcs11: Error opening configuration file '(null)'
p11-kit: yhsm2: module failed to initialize, skipping: The operation failed
p11-kit-trust: p11-kit-trust.so
    library-description: PKCS#11 Kit Trust Module
    library-manufacturer: PKCS#11 Kit
    library-version: 0.23
    token: Default Trust
        manufacturer: PKCS#11 Kit
        model: p11-kit-trust
        serial-number: 1
        hardware-version: 0.23
        flags:
               write-protected
               token-initialized
    token: System Trust
        manufacturer: PKCS#11 Kit
        model: p11-kit-trust
        serial-number: 1
        hardware-version: 0.23
        flags:
               write-protected
               token-initialized
pkcs11: /Library/OpenSC/lib/opensc-pkcs11.dylib
    library-description: OpenSC smartcard framework
    library-manufacturer: OpenSC Project
    library-version: 0.17
softhsm: /opt/local/lib/softhsm/libsofthsm2.dylib
    library-description: Implementation of PKCS11
    library-manufacturer: SoftHSM
    library-version: 2.3
    token: Botan PKCS#11 tests
        manufacturer: SoftHSM project
        model: SoftHSM v2
        serial-number: b158018a21bc4979
        hardware-version: 2.3
        firmware-version: 2.3
        flags:
               rng
               login-required
               user-pin-initialized
               restore-key-not-needed
               token-initialized
    token: test
        manufacturer: SoftHSM project
        model: SoftHSM v2
        serial-number: 02b891b82879828e
        hardware-version: 2.3
        firmware-version: 2.3
        flags:
               rng
               login-required
               user-pin-initialized
               restore-key-not-needed
               token-initialized
    token: 
        manufacturer: SoftHSM project
        model: SoftHSM v2
        serial-number: 
        hardware-version: 2.3
        firmware-version: 2.3
        flags:
               rng
               login-required
               restore-key-not-needed
               so-pin-locked
               so-pin-to-be-changed
ykcs11: /usr/local/lib/libykcs11.dylib
    library-description: PKCS#11 PIV Library (SP-800-73)
    library-manufacturer: Yubico (www.yubico.com)
    library-version: 1.44
$ cat ~/.config/pkcs11/modules/yhsm2.module 
module: /usr/local/lib/yubihsm_pkcs11.dylib
$
mouse07410 2017-10-9
3

更新
看起来像是将 critical: no 添加到 yhsm2.module 解决了问题...?

$ p11-kit list-modules
p11-kit-trust: p11-kit-trust.so
    library-description: PKCS#11 Kit Trust Module
    library-manufacturer: PKCS#11 Kit
    library-version: 0.23
    token: Default Trust
        manufacturer: PKCS#11 Kit
        model: p11-kit-trust
        serial-number: 1
        hardware-version: 0.23
        flags:
               write-protected
               token-initialized
    token: System Trust
        manufacturer: PKCS#11 Kit
        model: p11-kit-trust
        serial-number: 1
        hardware-version: 0.23
        flags:
               write-protected
               token-initialized
pkcs11: /Library/OpenSC/lib/opensc-pkcs11.dylib
    library-description: OpenSC smartcard framework
    library-manufacturer: OpenSC Project
    library-version: 0.17
softhsm: /opt/local/lib/softhsm/libsofthsm2.dylib
    library-description: Implementation of PKCS11
    library-manufacturer: SoftHSM
    library-version: 2.3
    token: Botan PKCS#11 tests
        manufacturer: SoftHSM project
        model: SoftHSM v2
        serial-number: b158018a21bc4979
        hardware-version: 2.3
        firmware-version: 2.3
        flags:
               rng
               login-required
               user-pin-initialized
               restore-key-not-needed
               token-initialized
    token: test
        manufacturer: SoftHSM project
        model: SoftHSM v2
        serial-number: 02b891b82879828e
        hardware-version: 2.3
        firmware-version: 2.3
        flags:
               rng
               login-required
               user-pin-initialized
               restore-key-not-needed
               token-initialized
    token: 
        manufacturer: SoftHSM project
        model: SoftHSM v2
        serial-number: 
        hardware-version: 2.3
        firmware-version: 2.3
        flags:
               rng
               login-required
               restore-key-not-needed
               so-pin-locked
               so-pin-to-be-changed
yhsm2: /usr/local/lib/yubihsm_pkcs11.dylib
    library-description: YubiHSM PKCS#11 Library
    library-manufacturer: Yubico (www.yubico.com)
    library-version: 0.9
    token: YubiHSM
        manufacturer: Yubico (www.yubico.com)
        model: YubiHSM
        serial-number: 056xxxxx
        hardware-version: 0.100
        firmware-version: 0.100
        flags:
               rng
               login-required
               user-pin-initialized
               token-initialized
ykcs11: /usr/local/lib/libykcs11.dylib
    library-description: PKCS#11 PIV Library (SP-800-73)
    library-manufacturer: Yubico (www.yubico.com)
    library-version: 1.44
$ 

但是当我尝试使用这个 yhsm2 引擎时, 我从 OpenSSL 中得到了错误:

$ OPENSSL_CONF=~/src/openssl.cnf openssl engine -t -c pkcs11
(pkcs11) pkcs11 engine
 [RSA]
     [ available ]
$ OPENSSL_CONF=~/src/openssl.cnf openssl engine -t -c yhsm2
bad engine id
140736391603208:error:260B606D:engine routines:DYNAMIC_LOAD:init failed:eng_dyn.c:545:
140736391603208:error:2606A074:engine routines:ENGINE_by_id:no such engine:eng_list.c:390:id=yhsm2
$

我 symlinked libpkcs11.dylib to libyhsm2.dylib , 因为我希望 libp11 处理此问题..。下面是我的 openssl.cnf 的尾部:

. . . . .
[engine_section]
pkcs11 = pkcs11_section
yhsm2  = yhsm2_section

[pkcs11_section]
engine_id = pkcs11
dynamic_path = /opt/local/lib/engines/libpkcs11.so
MODULE_PATH = /Library/OpenSC/lib/opensc-pkcs11.so
init = 0

[yhsm2_section]
engine_id = yhsm2
dynamic_path = /opt/local/lib/engines/libyhsm2.dylib
MODULE_PATH = /usr/local/lib/yubihsm_pkcs11.dylib
init = 0

还有一件事我还没想到, 就是如何把这些联系起来。例如, 如何通知 p11-kit 和/或 libp11 当我要使用 pkcs11.module 、何时 ykcs11.module 以及何时- yhsm2.module 。 我试图将模块 yhsm2 由 symlinking libpkcs11.dylib 显式定义为 libyhsm2.dylib , 但它没有完全工作。

它看起来像我必须坚持与引擎 pkcs11 定义, 如果我想使用 libp11 -除非有一些配置技巧, 我现在知道。如何选择并验证用于请求的库 ( opensc-pkcs11.dylibyubihsm_pkcs11.dylib ), 例如 $ openssl rand -engine pkcs11 128 -hex

原文:

Update
Looks like adding critical: no to the yhsm2.module resolved the problem...?

$ p11-kit list-modules
p11-kit-trust: p11-kit-trust.so
    library-description: PKCS#11 Kit Trust Module
    library-manufacturer: PKCS#11 Kit
    library-version: 0.23
    token: Default Trust
        manufacturer: PKCS#11 Kit
        model: p11-kit-trust
        serial-number: 1
        hardware-version: 0.23
        flags:
               write-protected
               token-initialized
    token: System Trust
        manufacturer: PKCS#11 Kit
        model: p11-kit-trust
        serial-number: 1
        hardware-version: 0.23
        flags:
               write-protected
               token-initialized
pkcs11: /Library/OpenSC/lib/opensc-pkcs11.dylib
    library-description: OpenSC smartcard framework
    library-manufacturer: OpenSC Project
    library-version: 0.17
softhsm: /opt/local/lib/softhsm/libsofthsm2.dylib
    library-description: Implementation of PKCS11
    library-manufacturer: SoftHSM
    library-version: 2.3
    token: Botan PKCS#11 tests
        manufacturer: SoftHSM project
        model: SoftHSM v2
        serial-number: b158018a21bc4979
        hardware-version: 2.3
        firmware-version: 2.3
        flags:
               rng
               login-required
               user-pin-initialized
               restore-key-not-needed
               token-initialized
    token: test
        manufacturer: SoftHSM project
        model: SoftHSM v2
        serial-number: 02b891b82879828e
        hardware-version: 2.3
        firmware-version: 2.3
        flags:
               rng
               login-required
               user-pin-initialized
               restore-key-not-needed
               token-initialized
    token: 
        manufacturer: SoftHSM project
        model: SoftHSM v2
        serial-number: 
        hardware-version: 2.3
        firmware-version: 2.3
        flags:
               rng
               login-required
               restore-key-not-needed
               so-pin-locked
               so-pin-to-be-changed
yhsm2: /usr/local/lib/yubihsm_pkcs11.dylib
    library-description: YubiHSM PKCS#11 Library
    library-manufacturer: Yubico (www.yubico.com)
    library-version: 0.9
    token: YubiHSM
        manufacturer: Yubico (www.yubico.com)
        model: YubiHSM
        serial-number: 056xxxxx
        hardware-version: 0.100
        firmware-version: 0.100
        flags:
               rng
               login-required
               user-pin-initialized
               token-initialized
ykcs11: /usr/local/lib/libykcs11.dylib
    library-description: PKCS#11 PIV Library (SP-800-73)
    library-manufacturer: Yubico (www.yubico.com)
    library-version: 1.44
$ 

But when I try to use this yhsm2 engine, I'm getting error from OpenSSL:

$ OPENSSL_CONF=~/src/openssl.cnf openssl engine -t -c pkcs11
(pkcs11) pkcs11 engine
 [RSA]
     [ available ]
$ OPENSSL_CONF=~/src/openssl.cnf openssl engine -t -c yhsm2
bad engine id
140736391603208:error:260B606D:engine routines:DYNAMIC_LOAD:init failed:eng_dyn.c:545:
140736391603208:error:2606A074:engine routines:ENGINE_by_id:no such engine:eng_list.c:390:id=yhsm2
$

I symlinked libpkcs11.dylib to libyhsm2.dylib because I wanted libp11 to take care of this... Here's the tail of my openssl.cnf:

. . . . .
[engine_section]
pkcs11 = pkcs11_section
yhsm2  = yhsm2_section

[pkcs11_section]
engine_id = pkcs11
dynamic_path = /opt/local/lib/engines/libpkcs11.so
MODULE_PATH = /Library/OpenSC/lib/opensc-pkcs11.so
init = 0

[yhsm2_section]
engine_id = yhsm2
dynamic_path = /opt/local/lib/engines/libyhsm2.dylib
MODULE_PATH = /usr/local/lib/yubihsm_pkcs11.dylib
init = 0

Another thing I haven't figured out is how exactly to tie all these together. I.e., how to inform p11-kit and/or libp11 when I want to use pkcs11.module, when ykcs11.module, and when - yhsm2.module. I tried to explicitly define module yhsm2 by symlinking libpkcs11.dylib to libyhsm2.dylib, but it did not quite work.

It looks like I have to stick with engine pkcs11 definition if I want to use libp11 - unless there's some config trick that I'm now aware of. How can I choose and then verify which library (opensc-pkcs11.dylib or yubihsm_pkcs11.dylib) is used for a request, such as $ openssl rand -engine pkcs11 128 -hex?

nmav 2017-10-9
4
原文:
dengert 2017-10-9
5
原文:
mouse07410 2017-10-9
6

我的经验与御笔 pkcs11 模块是, 他们往往是不完整的和半烘烤。

这里没有我的论据!;-)

p11tool 显示该模块的任何内容吗?

是的:

$ p11tool --list-tokens
Token 0:
	URL: pkcs11:model=p11-kit-trust;manufacturer=PKCS%2311%20Kit;serial=1;token=Default%20Trust
	Label: Default Trust
	Type: Trust module
	Manufacturer: PKCS#11 Kit
	Model: p11-kit-trust
	Serial: 1
	Module: p11-kit-trust.so


Token 1:
	URL: pkcs11:model=p11-kit-trust;manufacturer=PKCS%2311%20Kit;serial=1;token=System%20Trust
	Label: System Trust
	Type: Trust module
	Manufacturer: PKCS#11 Kit
	Model: p11-kit-trust
	Serial: 1
	Module: p11-kit-trust.so


Token 2:
	URL: pkcs11:model=SoftHSM%20v2;manufacturer=SoftHSM%20project;serial=b158018a21bc4979;token=Botan%20PKCS%2311%20tests
	Label: Botan PKCS#11 tests
	Type: Generic token
	Manufacturer: SoftHSM project
	Model: SoftHSM v2
	Serial: b158018a21bc4979
	Module: /opt/local/lib/softhsm/libsofthsm2.dylib


Token 3:
	URL: pkcs11:model=SoftHSM%20v2;manufacturer=SoftHSM%20project;serial=02b891b82879828e;token=test
	Label: test
	Type: Generic token
	Manufacturer: SoftHSM project
	Model: SoftHSM v2
	Serial: 02b891b82879828e
	Module: /opt/local/lib/softhsm/libsofthsm2.dylib


Token 4:
	URL: pkcs11:model=YubiHSM;manufacturer=Yubico%20%28www.yubico.com%29;serial=056xxxxx;token=YubiHSM
	Label: YubiHSM
	Type: Hardware token
	Manufacturer: Yubico (www.yubico.com)
	Model: YubiHSM
	Serial: 056xxxxx
	Module: /usr/local/lib/yubihsm_pkcs11.dylib


$ p11tool --login --list-all "pkcs11:model=YubiHSM;manufacturer=Yubico%20%28www.yubico.com%29;serial=056xxxxx;token=YubiHSM"
Token 'YubiHSM' with URL 'pkcs11:model=YubiHSM;manufacturer=Yubico%20%28www.yubico.com%29;serial=056xxxxx;token=YubiHSM' requires user PIN
Enter PIN: 
Object 0:
	URL: pkcs11:model=YubiHSM;manufacturer=Yubico%20%28www.yubico.com%29;serial=056xxxxx;token=YubiHSM;id=%00%01;object=DEFAULT%20AUTHKEY%20CHANGE%20THIS%20ASAP;type=secret-key
	Type: Secret key
	Label: DEFAULT AUTHKEY CHANGE THIS ASAP
	Flags: CKA_PRIVATE; CKA_EXTRACTABLE; CKA_SENSITIVE; 
	ID: 00:01

Object 1:
	URL: pkcs11:model=YubiHSM;manufacturer=Yubico%20%28www.yubico.com%29;serial=056xxxxx;token=YubiHSM;id=%8a%17;object=label%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00;type=secret-key
	Type: Secret key
	Label: label
	Flags: CKA_PRIVATE; CKA_NEVER_EXTRACTABLE; CKA_SENSITIVE; 
	ID: 8a:17

Object 2:
	URL: pkcs11:model=YubiHSM;manufacturer=Yubico%20%28www.yubico.com%29;serial=056xxxxx;token=YubiHSM;id=%8f%b8;object=label%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00;type=private
	Type: Private key
	Label: label
	Flags: CKA_PRIVATE; CKA_NEVER_EXTRACTABLE; CKA_SENSITIVE; 
	ID: 8f:b8

Object 3:
	URL: pkcs11:model=YubiHSM;manufacturer=Yubico%20%28www.yubico.com%29;serial=056xxxxx;token=YubiHSM;id=%8f%b8;object=label%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00;type=public
	Type: Public key
	Label: label
	Flags: CKA_EXTRACTABLE; 
	ID: 8f:b8

Object 4:
	URL: pkcs11:model=YubiHSM;manufacturer=Yubico%20%28www.yubico.com%29;serial=056xxxxx;token=YubiHSM;id=%8f%b8;object=label%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00;type=cert
	Type: X.509 Certificate
	Label: label
	Flags: CKA_PRIVATE; 
	ID: 8f:b8

Object 5:
	URL: pkcs11:model=YubiHSM;manufacturer=Yubico%20%28www.yubico.com%29;serial=056xxxxx;token=YubiHSM;id=%d7%41;object=label%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00;type=private
	Type: Private key
	Label: label
	Flags: CKA_PRIVATE; CKA_NEVER_EXTRACTABLE; CKA_SENSITIVE; 
	ID: d7:41

Object 6:
	URL: pkcs11:model=YubiHSM;manufacturer=Yubico%20%28www.yubico.com%29;serial=056xxxxx;token=YubiHSM;id=%d7%41;object=label%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00;type=public
	Type: Public key
	Label: label
	Flags: CKA_EXTRACTABLE; 
	ID: d7:41

$ 

https://www.yubico.com/products/yubihsm/说:..。

是的, 这是他们第一次尝试销售一个 HSM 设备, 实际上它是相当有限的 (aka 不适合我的需要-没有不对称, 等等)。

这是他们的第二版本, 它仍然是在测试版-所以你不能找到它在一个产品的网站还。他们仍然在增强和改进它 ("它" 适用于硬件、软件和文档)。

您是否可以获得 OpenSC pkcs11-tool 来列出 /usr/local/lib/yubihsm_pkcs11.so 的支持的机制?

是的, 你打赌:

$ pkcs11-tool --module $YUBIHSM_PKCS11_MODULE -M
Using slot 0 with a present token (0x0)
Supported mechanisms:
  RSA-PKCS, keySize={2048,4096}, hw, decrypt, sign
  SHA1-RSA-PKCS, keySize={2048,4096}, hw, decrypt, sign
  SHA256-RSA-PKCS, keySize={2048,4096}, hw, decrypt, sign
  SHA384-RSA-PKCS, keySize={2048,4096}, hw, decrypt, sign
  SHA512-RSA-PKCS, keySize={2048,4096}, hw, decrypt, sign
  RSA-PKCS-PSS, keySize={2048,4096}, hw, sign
  SHA1-RSA-PKCS-PSS, keySize={2048,4096}, hw, sign
  SHA256-RSA-PKCS-PSS, keySize={2048,4096}, hw, sign
  SHA384-RSA-PKCS-PSS, keySize={2048,4096}, hw, sign
  SHA512-RSA-PKCS-PSS, keySize={2048,4096}, hw, sign
  RSA-PKCS-KEY-PAIR-GEN, keySize={2048,4096}, hw, generate_key_pair
  ECDSA-KEY-PAIR-GEN, keySize={256,521}, hw, generate_key_pair, other flags=0x1500000
  SHA-1-HMAC, keySize={1,512}, hw, sign, verify
  SHA256-HMAC, keySize={1,512}, hw, sign, verify
  SHA384-HMAC, keySize={1,1024}, hw, sign, verify
  SHA512-HMAC, keySize={1,1024}, hw, sign, verify
  ECDSA, keySize={256,521}, hw, sign, other flags=0x1500000
  ECDSA-SHA1, keySize={256,521}, hw, sign, other flags=0x1500000
  ECDSA-SHA256, keySize={256,521}, hw, sign, other flags=0x1500000
  ECDSA-SHA348, keySize={256,521}, hw, sign, other flags=0x1500000
  ECDSA-SHA512, keySize={256,521}, hw, sign, other flags=0x1500000
  RSA-PKCS-OAEP, keySize={2048,4096}, hw, decrypt
  mechtype-0x80000004, keySize={128,128}, hw, wrap
  SHA-1, digest
  SHA256, digest
  SHA384, digest
  SHA512, digest
  GENERIC-SECRET-KEY-GEN, keySize={128,128}, hw, generate
$ 

AFAIK libp11 和它的引擎只支持使用非对称密钥 RSA 和 EC 通过引擎。(听起来像一个未来的项目。

是否确定?它能访问令牌提供的 RNG 吗?也就是说, 如果我以编程方式通过 OpenSSL+libp11 来访问一个令牌, 并且想从它的 RNG 中得到一些随机性, 我应该可以, 对不对?

我不认为在 github.com/yubico yubihsm, 所以它可能不是开源的。

不, 至少还没有 (但这要由 Yubico 决定)。

看看是否与 p11-kit, 你能得到一个 PKCS#11 的痕迹。你可以在 yubihsm_pkcs11 前用 opensc 间谍

要做到这一点, 我需要设置 YUBIHSM_PKCS11_MODULE=/Library/OpenSC/lib/opensc-spy.dylibPKCS11SPY=/usr/local/lib/yubihsm_pkcs11.dylib , 并运行 p11-kit?权利?

原文:

My experience with yubi pkcs11 modules is that they are often incomplete and half baked.

No argument from me here! ;-)

Does p11tool show anything for that module?

Yep:

$ p11tool --list-tokens
Token 0:
	URL: pkcs11:model=p11-kit-trust;manufacturer=PKCS%2311%20Kit;serial=1;token=Default%20Trust
	Label: Default Trust
	Type: Trust module
	Manufacturer: PKCS#11 Kit
	Model: p11-kit-trust
	Serial: 1
	Module: p11-kit-trust.so


Token 1:
	URL: pkcs11:model=p11-kit-trust;manufacturer=PKCS%2311%20Kit;serial=1;token=System%20Trust
	Label: System Trust
	Type: Trust module
	Manufacturer: PKCS#11 Kit
	Model: p11-kit-trust
	Serial: 1
	Module: p11-kit-trust.so


Token 2:
	URL: pkcs11:model=SoftHSM%20v2;manufacturer=SoftHSM%20project;serial=b158018a21bc4979;token=Botan%20PKCS%2311%20tests
	Label: Botan PKCS#11 tests
	Type: Generic token
	Manufacturer: SoftHSM project
	Model: SoftHSM v2
	Serial: b158018a21bc4979
	Module: /opt/local/lib/softhsm/libsofthsm2.dylib


Token 3:
	URL: pkcs11:model=SoftHSM%20v2;manufacturer=SoftHSM%20project;serial=02b891b82879828e;token=test
	Label: test
	Type: Generic token
	Manufacturer: SoftHSM project
	Model: SoftHSM v2
	Serial: 02b891b82879828e
	Module: /opt/local/lib/softhsm/libsofthsm2.dylib


Token 4:
	URL: pkcs11:model=YubiHSM;manufacturer=Yubico%20%28www.yubico.com%29;serial=056xxxxx;token=YubiHSM
	Label: YubiHSM
	Type: Hardware token
	Manufacturer: Yubico (www.yubico.com)
	Model: YubiHSM
	Serial: 056xxxxx
	Module: /usr/local/lib/yubihsm_pkcs11.dylib


$ p11tool --login --list-all "pkcs11:model=YubiHSM;manufacturer=Yubico%20%28www.yubico.com%29;serial=056xxxxx;token=YubiHSM"
Token 'YubiHSM' with URL 'pkcs11:model=YubiHSM;manufacturer=Yubico%20%28www.yubico.com%29;serial=056xxxxx;token=YubiHSM' requires user PIN
Enter PIN: 
Object 0:
	URL: pkcs11:model=YubiHSM;manufacturer=Yubico%20%28www.yubico.com%29;serial=056xxxxx;token=YubiHSM;id=%00%01;object=DEFAULT%20AUTHKEY%20CHANGE%20THIS%20ASAP;type=secret-key
	Type: Secret key
	Label: DEFAULT AUTHKEY CHANGE THIS ASAP
	Flags: CKA_PRIVATE; CKA_EXTRACTABLE; CKA_SENSITIVE; 
	ID: 00:01

Object 1:
	URL: pkcs11:model=YubiHSM;manufacturer=Yubico%20%28www.yubico.com%29;serial=056xxxxx;token=YubiHSM;id=%8a%17;object=label%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00;type=secret-key
	Type: Secret key
	Label: label
	Flags: CKA_PRIVATE; CKA_NEVER_EXTRACTABLE; CKA_SENSITIVE; 
	ID: 8a:17

Object 2:
	URL: pkcs11:model=YubiHSM;manufacturer=Yubico%20%28www.yubico.com%29;serial=056xxxxx;token=YubiHSM;id=%8f%b8;object=label%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00;type=private
	Type: Private key
	Label: label
	Flags: CKA_PRIVATE; CKA_NEVER_EXTRACTABLE; CKA_SENSITIVE; 
	ID: 8f:b8

Object 3:
	URL: pkcs11:model=YubiHSM;manufacturer=Yubico%20%28www.yubico.com%29;serial=056xxxxx;token=YubiHSM;id=%8f%b8;object=label%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00;type=public
	Type: Public key
	Label: label
	Flags: CKA_EXTRACTABLE; 
	ID: 8f:b8

Object 4:
	URL: pkcs11:model=YubiHSM;manufacturer=Yubico%20%28www.yubico.com%29;serial=056xxxxx;token=YubiHSM;id=%8f%b8;object=label%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00;type=cert
	Type: X.509 Certificate
	Label: label
	Flags: CKA_PRIVATE; 
	ID: 8f:b8

Object 5:
	URL: pkcs11:model=YubiHSM;manufacturer=Yubico%20%28www.yubico.com%29;serial=056xxxxx;token=YubiHSM;id=%d7%41;object=label%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00;type=private
	Type: Private key
	Label: label
	Flags: CKA_PRIVATE; CKA_NEVER_EXTRACTABLE; CKA_SENSITIVE; 
	ID: d7:41

Object 6:
	URL: pkcs11:model=YubiHSM;manufacturer=Yubico%20%28www.yubico.com%29;serial=056xxxxx;token=YubiHSM;id=%d7%41;object=label%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00;type=public
	Type: Public key
	Label: label
	Flags: CKA_EXTRACTABLE; 
	ID: d7:41

$ 

https://www.yubico.com/products/yubihsm/ says: ...

Yes, that was their first attempt to sell an HSM device, and indeed it was rather limited (aka unsuitable for my needs - no asymmetric, etc.).

This is their 2nd version, and it's still in Beta - so you can't find it on a product site yet. They are still enhancing and improving it ("it" applies to hardware, software, and documentation).

Can you get OpenSC pkcs11-tool to list the mechanisms supported by the /usr/local/lib/yubihsm_pkcs11.so?

Yep, you bet:

$ pkcs11-tool --module $YUBIHSM_PKCS11_MODULE -M
Using slot 0 with a present token (0x0)
Supported mechanisms:
  RSA-PKCS, keySize={2048,4096}, hw, decrypt, sign
  SHA1-RSA-PKCS, keySize={2048,4096}, hw, decrypt, sign
  SHA256-RSA-PKCS, keySize={2048,4096}, hw, decrypt, sign
  SHA384-RSA-PKCS, keySize={2048,4096}, hw, decrypt, sign
  SHA512-RSA-PKCS, keySize={2048,4096}, hw, decrypt, sign
  RSA-PKCS-PSS, keySize={2048,4096}, hw, sign
  SHA1-RSA-PKCS-PSS, keySize={2048,4096}, hw, sign
  SHA256-RSA-PKCS-PSS, keySize={2048,4096}, hw, sign
  SHA384-RSA-PKCS-PSS, keySize={2048,4096}, hw, sign
  SHA512-RSA-PKCS-PSS, keySize={2048,4096}, hw, sign
  RSA-PKCS-KEY-PAIR-GEN, keySize={2048,4096}, hw, generate_key_pair
  ECDSA-KEY-PAIR-GEN, keySize={256,521}, hw, generate_key_pair, other flags=0x1500000
  SHA-1-HMAC, keySize={1,512}, hw, sign, verify
  SHA256-HMAC, keySize={1,512}, hw, sign, verify
  SHA384-HMAC, keySize={1,1024}, hw, sign, verify
  SHA512-HMAC, keySize={1,1024}, hw, sign, verify
  ECDSA, keySize={256,521}, hw, sign, other flags=0x1500000
  ECDSA-SHA1, keySize={256,521}, hw, sign, other flags=0x1500000
  ECDSA-SHA256, keySize={256,521}, hw, sign, other flags=0x1500000
  ECDSA-SHA348, keySize={256,521}, hw, sign, other flags=0x1500000
  ECDSA-SHA512, keySize={256,521}, hw, sign, other flags=0x1500000
  RSA-PKCS-OAEP, keySize={2048,4096}, hw, decrypt
  mechtype-0x80000004, keySize={128,128}, hw, wrap
  SHA-1, digest
  SHA256, digest
  SHA384, digest
  SHA512, digest
  GENERIC-SECRET-KEY-GEN, keySize={128,128}, hw, generate
$ 

AFAIK libp11 and its engine only support the use of asymmetric keys RSA and EC via the engine. (Sounds like a future project.)

Are you sure? Can it access RNG that the token provides? I.e., if I'm accessing a token programmatically via OpenSSL+libp11, and want to get some randomness from its RNG - I should be able to, right?

I don't see on github.com/yubico a yubihsm so it may not be open source.

No, not yet at least (but that's up to Yubico to decide).

To see if trying it with p11-kit, can you get a PKCS#11 trace. You could use opensc-spy in front of yubihsm_pkcs11.

To do that I would need to set YUBIHSM_PKCS11_MODULE=/Library/OpenSC/lib/opensc-spy.dylib and PKCS11SPY=/usr/local/lib/yubihsm_pkcs11.dylib, and run p11-kit? Right?

dengert 2017-10-9
7

看起来你有两种方法来使用 OpenSSL 作为引擎的 yubihsm。
您指的是尝试:

[yhsm2_section]
engine_id = yhsm2
dynamic_path = /opt/local/lib/engines/libyhsm2.dylib
MODULE_PATH = /usr/local/lib/yubihsm_pkcs11.dylib
init = 0

libyhsm2 是 dylib 引擎模块吗?它叫 PKCS#11 吗?
是否需要加载其他库?ldd 或 MacOS 版本显示了需要加载的内容。

另一个选择是使用 libp11's 引擎, 并让它使用 p11-kit 或 PKCS#11 模块。
它看起来也像 yubihsm_pkcs11. dylib 不支持任何对称机制。

但我不认为对称密钥或随机的 libp11 也支持。
在 libp11 或御笔库中查找 ENGINE_SET_ 函数或 ENGINE_set_RAND 和 ENGNE_SET_ciphers。

原文:

It looks like you have two ways to use the yubihsm with OpenSSL as an engine.
You refer to trying:

[yhsm2_section]
engine_id = yhsm2
dynamic_path = /opt/local/lib/engines/libyhsm2.dylib
MODULE_PATH = /usr/local/lib/yubihsm_pkcs11.dylib
init = 0

Is libyhsm2.dylib an engine module? Does it call PKCS#11?
Does it need to load other libs? What does ldd or MacOS version show what it needs to load.

The other choice is to use libp11's engine, and let it use p11-kit or a PKCS#11 module.
It also looks like yubihsm_pkcs11.dylib does not support any symmetric mechanisms.

But I don't think symmetric keys or random are supported by libp11 either.
Look for ENGINE_SET_ functions or ENGINE_set_RAND and ENGNE_SET_ciphers in libp11 or the yubi libs.

mouse07410 2017-10-9
8

libyhsm2.dylib 引擎模块吗?它叫 PKCS#11 吗?是否需要加载其他库?

那是我丑陋的黑客我将 pkcs11.dylib (PKCS#11 引擎/库来自 libp11 ) 复制到 libyhsm2.dylib 。原因之一-因为最终我希望 libp11 引擎来处理这一点, 作为所有 PKCS#11 令牌支持的一部分 (CAC、PIV、Yubikey 和这个新的 Yubico HSM2 设备)。

ldd 或 MacOS 版本显示了需要加载的内容。

所有正常的事情-这是一个工作 libp11 的副本..。MacOS 版本为 $ otool -L /path/to/libyhsm2.dylib

另一个选择是使用 libp11's 引擎, 并让它使用 p11-kit 或 PKCS#11 模块。

由于我的当前安装已 libp11 使用 p11-kit , 因此我认为这是我希望遵循的路径。

它看起来也像 yubihsm_pkcs11. dylib 不支持任何对称机制。

你能给一个对称机制的例子, 所以我知道要看/检查?也就是说, 我如何告诉 pkcs11-tool 做一些 "对称" 的事情, 以及对对称机制的报告?

谢谢!

原文:

Is libyhsm2.dylib an engine module? Does it call PKCS#11? Does it need to load other libs?

Wel, that's my ugly hack. I took pkcs11.dylib (the PKCS#11 engine/library from libp11) and copied it to libyhsm2.dylib. One reason why - because ultimately I want the libp11 engine to handle this, as a part of all the PKCS#11 token support (CAC, PIV, Yubikey, and this new Yubico HSM2 device).

What does ldd or MacOS version show what it needs to load.

All the normal things - it's a copy of working libp11... The MacOS version is $ otool -L /path/to/libyhsm2.dylib.

The other choice is to use libp11's engine, and let it use p11-kit or a PKCS#11 module.

Since my current installation has libp11 using p11-kit, I think this is the path I'd like to follow.

It also looks like yubihsm_pkcs11.dylib does not support any symmetric mechanisms.

Could you give an example of a symmetric mechanism, so I know what to look/check for? I.e., how would I tell pkcs11-tool to do something "symmetric", and what would pkcs11-tool -M report for symmetric mechanisms?

Thanks!

mtrojnar 2017-10-9
9

你能举一个对称机制的例子吗

libp11 不支持对称算法。

原文:

Could you give an example of a symmetric mechanism

libp11 does not support symmetric algorithms.

mouse07410 2017-10-9
10

libp11 不支持对称算法。

好的,谢谢。我还想知道, 如果令牌本身支持对称算法, OpenSC 会报告什么, 这些算法 (通常) 除了哈希 (SHA x) 和 HMAC 之外, 还会是什么。

原文:

libp11 does not support symmetric algorithms.

OK, thanks. I still would like to know what OpenSC would report if the token itself supported symmetric algorithms, and what would those algorithms (typically) be, besides hash (SHA-x) and HMAC.

dengert 2017-10-9
11

@mouse您问: "pkcs11-tool-M 报告的对称机制:

pkcs11-工具. c 通过 static struct mech_info p11_mechanisms 映射 CKM_ * 或打印机制的十六进制值。 因此, 查找 CKM_AES_ (表中显示了表中所有的 PKCS#11 对称密钥机制)。_

你说你在 yubihsm 的测试版工作

https://www.yubico.com/products/yubihsm/
说它支持 AES。

那么, 为什么它不支持 AES 呢?(如果模块支持它, pkcs11-tool 应该已经列出它。
或者为什么网页说它支持 AES?

另外, 如果您有任何输入与 Yubico 在这有他们做某事使0x80000004 机制 Yubico 具体, 象什么网景做了。

原文:

@mouse you asked: "what would pkcs11-tool -M report for symmetric mechanisms:

pkcs11-tool.c maps CKM_* via the static struct mech_info p11_mechanisms or prints the HEX value of the mechanism. So look for CKM_AES_ (The table appears to have all the PKCS#11 symmetric key mechanisms in the table.)_

You said you were working with some beta version of the yubihsm.

https://www.yubico.com/products/yubihsm/
says it supports AES.

So why does it not support AES? (If the module supported it, pkcs11-tool -M should have listed it.)
Or why does the web page say it supports AES?

In addition, If you have any input with Yubico on this have them do something to make the 0x80000004 mechanism Yubico specific, like what Netscape did.

dengert 2017-10-9
12

@mouse您还询问: "我如何告诉 pkcs11-tool 做一些" 对称 "。

只是因为 pkcs11 工具 c 可以列出所有的机制, 它并不意味着它可以使用它们。

原文:

@mouse you also asked: " how would I tell pkcs11-tool to do something "symmetric".

Just because pkcs11-tool.c can list all the mechanisms, it does not mean it can use them.

mouse07410 2017-10-9
13

你说你在 yubihsm 的测试版工作

是的.这是前期生产。确切的规格尚未敲定。

https://www.yubico.com/products/yubihsm/表示它支持 AES。那么, 为什么它不支持 AES 呢?(如果模块支持它, pkcs11-tool 应该已经列出它。

是, 但该页用于不同的 HSM。也许这一个可以做同样的, 或者它可能会更符合 "大枪" HSM, 主要是审计不对称的东西, 如 CA 操作..。由于它是极不太可能使用一个 USB 连接的 HSM 与 Yubikey 纳米形式的因素, 卸载批量加密。

另外, 如果您有任何输入与 Yubico 在这有他们做某事使0x80000004 机制 Yubico 具体, 象什么网景做了。

我不能声称与他们有一拉, 但我当然可以通知的问题和建议的解决方案。你认为应该怎么做?也就是说, 应该改变什么?是物理设备报告的吗?或者是支持库 ("驱动程序") 将其映射到什么?而它应该 (不管它是什么) 被映射到什么?

原文:

You said you were working with some beta version of the yubihsm.

Yep. It is pre-production. Exact specs not finalized yet.

https://www.yubico.com/products/yubihsm/ says it supports AES. So why does it not support AES? (If the module supported it, pkcs11-tool -M should have listed it.)

Yeah, but that page is for a different HSM. Maybe this one would be able to do the same, or maybe it would be more in line with the "big guns" HSM that mostly do audited asymmetric things like CA operations... As it is highly unlikely one would use a USB-connected HSM with Yubikey-Nano form-factor to off-load bulk encryption to.

In addition, If you have any input with Yubico on this have them do something to make the 0x80000004 mechanism Yubico specific, like what Netscape did.

I cannot claim to have a pull with them, but I certainly can inform of issues and recommend solutions. In your opinion, what should be done? I.e., what should be changed and where? Is it what the physical device reports? Or is it what the supporting library (the "driver") maps it to? And what should it (whatever "it" is) be mapped to instead?

dengert 2017-10-9
14

@mouse07410 看到:
OpenSC/OpenSC#1131 (评论)
供应商如何制作 vendor_defined PKCS#11 类型。
我看你已经给它一个 "竖起大拇指" 了。

我建议 Yubico 使用59554200为 YUB, 这给然后多达256种不同的类型。
它有一个更好的变化是独特的, 当使用与 p11-kit 例如。

这些可以被添加到 pkcs11-tool 至少列出它们。我永远不会添加0x80000004 到 pkcs11-tool, 因为它几乎没有机会在多个模块的唯一性。

原文:

@mouse07410 See:
OpenSC/OpenSC#1131 (comment)
as to how a vendor can make vendor_defined PKCS#11 types.
I see you have given it a "thumbs up" already.

I would suggest Yubico use 59554200 for YUB This gives then up to 256 different types.
It has a better change of being unique when use with p11-kit for example.

And these could be added to pkcs11-tool to at least list them. I would never add 0x80000004 to pkcs11-tool, as it has little chance of being unique across multiple modules.

mouse07410 2017-10-9
15

@dengert如果我理解正确, 您建议

  • 定义 Yubico 的供应商类型代码, 例如,
    #define YUBICO_VENDOR_DEFINED 0x59554200
  • 将此特定代码定义为
    #define CKA_YUBICO_WHATEVER_OP ( CKA_VENDOR_DEFINED | YUBICO_VENDOR_DEFINED | 4UL)

正确?(如果是这样, 我一定会把这个传给 Yubico, 希望他们会做正确的事..。

原文:

@dengert so if I understand correctly, you suggest

  • define Yubico vendor type code, e.g.,
    #define YUBICO_VENDOR_DEFINED 0x59554200
  • define this specific code as
    #define CKA_YUBICO_WHATEVER_OP ( CKA_VENDOR_DEFINED | YUBICO_VENDOR_DEFINED | 4UL)

Correct? (If so, I will certainly pass this to Yubico, and hopefully they'd do the right thing...)

dengert 2017-10-9
16

是的。

原文:

Yes.

dengert 2017-10-9
17

除了我们讨论的机制, 所以它会是:
#define CKM_YUBICO_WHATEVER_MECH (CKM_VENDOR_DEFINED |YUBICO_VENDOR_DEFINED |4UL)

原文:

Except we were talking mechanisms, so it would be:
#define CKM_YUBICO_WHATEVER_MECH ( CKM_VENDOR_DEFINED | YUBICO_VENDOR_DEFINED | 4UL)

mouse07410 2017-10-9
18

提交.让我们拭目以待吧。;-)

原文:

Submitted. Let's wait and see now. ;-)

mouse07410 2017-10-9
19

我可以关闭这个问题。以下是我所学到的:

  • 要在 YubiHSM2 上使用 ID 为 0x0301 的私钥 (具有签名功能的 RSA), 密钥 URL 应pkcs11:token=YubiHSM;id=%03%01;type=private
  • 要在 Yubikey NEO 或4上使用私钥 SIGN key , 密钥 URL 应pkcs11:manufacturer=piv_II;object=SIGN%20key;type=private

问题: YubiHSM2 可以使用 RSA-PSS (例如使用 SHA384-RSA-PKCS-PSS 算法) 通过 yubihsm-shell 进行签名。但尝试通过 libp11OpenSC 访问它失败:

$ openssl dgst -sha384 -engine pkcs11 -keyform engine -sign "pkcs11:token=YubiHSM;id=%03%01;type=private" -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:-1 -out t2570.dat.sig4 t2570.dat
engine "pkcs11" set.
Enter PKCS#11 token PIN for YubiHSM:
Error Signing Data
140736391603208:error:8207A070:PKCS#11 module:pkcs11_private_encrypt:Mechanism invalid:p11_rsa.c:120:
$

做同样的事情与 Yubikey 的新作品:

$ openssl dgst -sha384 -engine pkcs11 -keyform engine -sign "pkcs11:manufacturer=piv_II;object=SIGN%20key;type=private" -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:-1 -out t2570.dat.sig4 t2570.dat
engine "pkcs11" set.
Enter PKCS#11 token PIN for PIV Card Holder pin (PIV_II):
Enter PKCS#11 key PIN for SIGN key:
$ openssl dgst -sha384 -engine pkcs11 -keyform engine -verify "pkcs11:manufacturer=piv_II;object=SIGN%20pubkey;type=public" -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:-1 -signature t2570.dat.sig4 t2570.dat
engine "pkcs11" set.
Verified OK
$

使用存储在 YubiHSM2 中的私钥验证由 yubihsm-shell 所做的 SHA384-RSA-PKCS-PSS 签名也很有效:

$ openssl dgst -sha384 -verify 301-rsa.pem -keyform PEM -sigopt rsa_padding_mode:pss -signature t2570.dat.sig t2570.dat
Verified OK
$ openssl dgst -sha384 -engine pkcs11 -keyform engine -verify "pkcs11:token=YubiHSM;id=%03%01;type=public" -sigopt rsa_padding_mode:pss -signature t2570.dat.sig t2570.dat
engine "pkcs11" set.
Enter PKCS#11 token PIN for YubiHSM:
Verified OK
$ 

RSASSA PKCS v1.5 签名也与 YubiHSM2 一起使用:

$ openssl dgst -sha384 -engine pkcs11 -keyform engine -sign "pkcs11:token=YubiHSM;id=%03%01;type=private" -sigopt rsa_padding_mode:pkcs1 -out t2570.dat.sig2 t2570.dat
engine "pkcs11" set.
Enter PKCS#11 token PIN for YubiHSM:
$ openssl dgst -sha384 -engine pkcs11 -keyform engine -verify "pkcs11:token=YubiHSM;id=%03%01;type=public" -sigopt rsa_padding_mode:pkcs1 -signature t2570.dat.sig2 t2570.dat
engine "pkcs11" set.
Enter PKCS#11 token PIN for YubiHSM:
Verified OK
$ 

有什么建议吗?

原文:

I can close this issue. Here's what I learned:

  • To use private key (RSA with signing capabilities) with ID 0x0301 on YubiHSM2, the key URL should be pkcs11:token=YubiHSM;id=%03%01;type=private
  • To use private key SIGN key on Yubikey NEO or 4, the key URL should be pkcs11:manufacturer=piv_II;object=SIGN%20key;type=private

The problem: YubiHSM2 can sign using RSA-PSS, for example with SHA384-RSA-PKCS-PSS algorithm, via yubihsm-shell. But trying to access it via libp11 or OpenSC fails:

$ openssl dgst -sha384 -engine pkcs11 -keyform engine -sign "pkcs11:token=YubiHSM;id=%03%01;type=private" -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:-1 -out t2570.dat.sig4 t2570.dat
engine "pkcs11" set.
Enter PKCS#11 token PIN for YubiHSM:
Error Signing Data
140736391603208:error:8207A070:PKCS#11 module:pkcs11_private_encrypt:Mechanism invalid:p11_rsa.c:120:
$

Doing the same thing with Yubikey NEO works:

$ openssl dgst -sha384 -engine pkcs11 -keyform engine -sign "pkcs11:manufacturer=piv_II;object=SIGN%20key;type=private" -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:-1 -out t2570.dat.sig4 t2570.dat
engine "pkcs11" set.
Enter PKCS#11 token PIN for PIV Card Holder pin (PIV_II):
Enter PKCS#11 key PIN for SIGN key:
$ openssl dgst -sha384 -engine pkcs11 -keyform engine -verify "pkcs11:manufacturer=piv_II;object=SIGN%20pubkey;type=public" -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:-1 -signature t2570.dat.sig4 t2570.dat
engine "pkcs11" set.
Verified OK
$

Verifying SHA384-RSA-PKCS-PSS signature made by yubihsm-shell with private key stored in YubiHSM2 also works fine:

$ openssl dgst -sha384 -verify 301-rsa.pem -keyform PEM -sigopt rsa_padding_mode:pss -signature t2570.dat.sig t2570.dat
Verified OK
$ openssl dgst -sha384 -engine pkcs11 -keyform engine -verify "pkcs11:token=YubiHSM;id=%03%01;type=public" -sigopt rsa_padding_mode:pss -signature t2570.dat.sig t2570.dat
engine "pkcs11" set.
Enter PKCS#11 token PIN for YubiHSM:
Verified OK
$ 

RSASSA PKCS v1.5 signatures also work with YubiHSM2:

$ openssl dgst -sha384 -engine pkcs11 -keyform engine -sign "pkcs11:token=YubiHSM;id=%03%01;type=private" -sigopt rsa_padding_mode:pkcs1 -out t2570.dat.sig2 t2570.dat
engine "pkcs11" set.
Enter PKCS#11 token PIN for YubiHSM:
$ openssl dgst -sha384 -engine pkcs11 -keyform engine -verify "pkcs11:token=YubiHSM;id=%03%01;type=public" -sigopt rsa_padding_mode:pkcs1 -signature t2570.dat.sig2 t2570.dat
engine "pkcs11" set.
Enter PKCS#11 token PIN for YubiHSM:
Verified OK
$ 

Any recommendations here?

dengert 2017-10-9
20

最有可能的问题是与卡或 libp11's 功能的差异有关。PIV 型设备支持机制 RSA-X509。YubiHSM 不基于上面的 pkcs11-tool -M 列表。 与 RSA-X509 (即原始 RSA) 上层软件 (如 OpenSSL) 可以做填充。但 YubiHSM 只支持 rsa-pkcs 和 rsa-pkcs PSS。

运行 PIV 和 YubiHSM 与间谍的痕迹, 看看是怎么回事。

原文:

Most likely the problem has to do with differences in the card's or libp11's capabilities. The PIV type devices support mechanism RSA-X509. The YubiHSM does not based on pkcs11-tool -M list above. With RSA-X509 (i.e. RAW RSA) upper levels of software (like OpenSSL) can do the padding. But the YubiHSM only supports RSA-PKCS and RSA-PKCS-PSS.

Run both PIV and YubiHSM with SPY traces to see what is going on.

dengert 2017-10-9
21

它看起来像 p11 不支持 PSS。
看 p11_rsa. c: pkcs11_mechanism () 它只了解 CKM_RSA_PKCS, CKM_RSA_X_509 和 CKM_RSA_X9_31。

原文:

And it looks like p11 does not support PSS.
look at p11_rsa.c: pkcs11_mechanism() It only understands CKM_RSA_PKCS, CKM_RSA_X_509 and CKM_RSA_X9_31.

mouse07410 2017-10-9
22

最有可能的问题是与卡或 libp11's 功能的差异有关。

我想你在说的是:

  • Yubikey NEO 只做 RSA-X509 , 因此, 正如 OpenSSL/libp11/OpenSC 所说, 它在软件中执行 RSA-PSS。所以它可以正常工作。
  • YubiHSM2 不支持原始 RSA-X509 、广告组合机制 (如 RSA-PKCS-PSSRSA-PKCS )。因此, OpenSSL 不尝试在软件中自行执行 PSS, 而是将请求传递给 libp11--在它失败的地方。

正确?

和一个天真的问题: 为什么它不失败的签名验证, 只有签署?因为验证实际上总是在软件中完成 (又不像私钥操作, 从卡中抽取公钥)?

它看起来像 p11 不支持 PSS。

@mtrojnar CKM_RSA_PKCS_PSS 在中添加机制需要什么?如果有某种检查, 它不会中止操作或试图要求令牌做 PSS, 如果它支持的是 RSA-X509?因此, 它不会打破 RSA-PSS 的标记 (如 PIV 和 Yubikey 的新), 只 RSA-X509 它的工作现在呢?

运行 PIV 和 YubiHSM 与间谍的痕迹, 看看是怎么回事。

将在这里做和张贴。

更新
成功的 RSA-PSS 间谍日志与 Yubikey NEO:
间谍-新的 txt

失败的 RSA-PSS 间谍日志与 YubiHSM2:
间谍-yhsm2

@mtrojnar因此, 我所要做的是 libp11 增强功能, 在令牌支持它时将 rsa-pss 请求传递到令牌, 并继续使用不支持 rsa-pss 的令牌请求 RSA-X509。是否可行?

原文:

Most likely the problem has to do with differences in the card's or libp11's capabilities.

What I think you're saying is:

  • Yubikey NEO does only RSA-X509, therefore as OpenSSL/libp11/OpenSC figures that out, it performs RSA-PSS in software. So it works correctly.
  • YubiHSM2 does not support raw RSA-X509, advertising combined mechanisms like RSA-PKCS-PSS and RSA-PKCS. Therefore OpenSSL does not try to do PSS by itself in software, but passes the request to libp11 - where it fails.

Correct?

And a naive question: why it does not fail on signature verification, only on signing? Because the verification is actually done always in software (aka public key is extracted from the card, unlike private key operations)?

And it looks like p11 does not support PSS.

@mtrojnar what would it take to add CKM_RSA_PKCS_PSS mechanism in? With some kind of a check that would not abort the operation or try to ask the token to do PSS if all it supports is RSA-X509? So it won't break RSA-PSS for tokens (like PIV and Yubikey NEO) that do only RSA-X509 where it works now?

Run both PIV and YubiHSM with SPY traces to see what is going on.

Will do and post here.

Update
Successful RSA-PSS spy log with Yubikey NEO:
spy-neo.txt

Failing RSA-PSS spy log with YubiHSM2:
spy-yhsm2.txt

@mtrojnar So what I'm essentially after is libp11 enhancement to pass RSA-PSS requests to the token when the token supports it, and to keep requesting RSA-X509 with the tokens that don't support RSA-PSS. Is it feasible?

mouse07410 2017-10-9
23

@mtrojnar

原文:

@mtrojnar ?

mtrojnar 2017-10-9
24

间谍日志证实了我在2016年3月对 OpenSSL 源代码的调查中发现的内容:
OpenSSL 从不请求引擎的 PSS 填充。 相反, 它请求 RSA_NO_PADDING (转换为 PKCS#11 的 CKM_RSA_X_509), 并在内部处理填充。

显然 YubiHSM2 不支持 CKM_RSA_X_509:

[in] hSession = 0x0
pMechanism->type=CKM_RSA_X_509                
[in] hKey = 0x30301
Returned:  112 CKR_MECHANISM_INVALID

我不认为我们可以改变 OpenSSL 的实施在 libp11 或引擎。

原文:

The spy logs confirm what I found during my investigation of the OpenSSL source code in March 2016:
OpenSSL never requests the PSS padding from an engine. Instead, it requests RSA_NO_PADDING (which translates into CKM_RSA_X_509 for PKCS#11), and handles the padding internally.

Apparently, YubiHSM2 doesn't support CKM_RSA_X_509:

[in] hSession = 0x0
pMechanism->type=CKM_RSA_X_509                
[in] hKey = 0x30301
Returned:  112 CKR_MECHANISM_INVALID

I don't think we can change the OpenSSL's implementation from within libp11 or the engine.

mtrojnar 2017-10-9
25

@mouse07410: 我们已经讨论了一个非常类似的主题: #70 (注释)

原文:

@mouse07410: We already discussed a very similar topic: #70 (comment)

mouse07410 2017-10-9
26

@mtrojnar是的, 谢谢你提醒我。这是一个伟大的工作!

显然 YubiHSM2 不支持CKM_RSA_X_509

我试图说服 HSM2 的开发人员添加对 RSA-X-509 的支持。

我预见困难, 因为 HSM2 是基于。每个键都分配了不可变的功能, 如 asymmetric_sign_pss 和/或 asymmetric_sign_pkcs 。因此, 如果他们添加对 RSA-X-509 的支持, 你将无法只限制 PSS 签名的密钥, 并使用 OpenSSL/libp11..。

你对这个问题有什么看法?

谢谢!

原文:

@mtrojnar yes indeed, thank you for reminding me. It was a great work!

Apparently, YubiHSM2 doesn't support CKM_RSA_X_509

I'm trying to convince the developers of HSM2 to add support for RSA-X-509.

I envision difficulties because HSM2 is capabilities-based. Each key is assigned immutable capabilities, such as asymmetric_sign_pss and/or asymmetric_sign_pkcs. So if they add support for RSA-X-509, one would be unable to restrict the key to PSS signatures only, and use OpenSSL/libp11 with it...

What's your opinion on this problem?

Thanks!

mtrojnar 2017-10-9
27

允许 CKM_RSA_X_509 (原始 RSA) 用于现有的仅签名密钥将是一个坏主意。 最好使用单独的密钥, 它具有允许 CKM_RSA_X_509 的功能。

另一种方法是将 OpenSSL 引擎 API 扩展到可选择的调用其他机制, 如 RSA_PKCS1_PSS_PADDING, 直接从引擎。 最好是, 引擎应该能够声明它们直接支持特定密钥的机制。 我们还需要扩展 libp11, 将 OpenSSL RSA_PKCS1_PSS_PADDING 参数转换为 PKCS#11 CKM_RSA_PKCS_PSS 参数。

原文:

Allowing CKM_RSA_X_509 (raw RSA) for existing signature-only keys would be a bad idea. It would be better to use separate keys, which have a capability allowing for CKM_RSA_X_509.

An alternative approach would be to extend the OpenSSL engine API to optionally invoke additional mechanisms, such as RSA_PKCS1_PSS_PADDING, directly from an engine. Preferably, engines should be able to declare which mechanisms they directly support for a specific key. We would also need to extend libp11 to translate OpenSSL RSA_PKCS1_PSS_PADDING parameters into PKCS#11 CKM_RSA_PKCS_PSS parameters.

dengert 2017-10-9
28

这里是另一种方法, 不需要 OpenSSL mods。

当引擎和/或 libp11 看到加密使用 CKM_RSA_X_509, 但 PKCS#11 模块不支持它时, 可以对要加密的块进行检查, 以查看它是否看起来像 RSA_PKCS1_PSS_PADDING。由于在这一点上没有加密, 因此可能会得到 CKM_RSA_PKCS_PSS 参数所需的信息, 就像验证操作一样。

https://tools.ietf.org/html/rfc8017#section-9.1。2
显示进行验证所需的内容EMSA-PSS-VERIFY (M, EM, emBits)

这可能需要实现 ENGINE_set_digests, 以便捕获 M、EM 和哈希。
但这需要做之前, 引擎知道这将是一个 PSS 操作, 所以每一个文摘将 traped, 至少最后一个保存。

(可能更容易 "扩展 OpenSSL 引擎 API", 如@mtrojnar所建议的那样, 并使 OpenSSL 接受更改。

另一种方法是使用 LD_PRELOAD 替换 RSA_padding_add_PKCS1_PSS 来传递参数以填充 CKM_RSA_PKCS_PSS。但这可能对所有操作系统都无效。

但是, 要开发这一功能, 需要一个支持软件或硬件 PSS 的 PKCS#11 模块。
现在还不清楚这是否奏效。

@mouse07410您需要此操作有多严重?

原文:

Here is another approach that does not require OpenSSL mods.

When the engine and/or libp11 sees an encryption to use CKM_RSA_X_509 but the PKCS#11 module does not support it, the block to be encrypted could be examined to see if it is looks like RSA_PKCS1_PSS_PADDING. Since it is not encrypted at this point it might be possible to get the information needed for CKM_RSA_PKCS_PSS parameters much like a verify operation does.

https://tools.ietf.org/html/rfc8017#section-9.1.2
shows what is needed to do a verify EMSA-PSS-VERIFY (M, EM, emBits)

This might require implementing ENGINE_set_digests so as to trap M, EM, and Hash.
But this would need to be done before the engine knew it would be a PSS operation, so every digest would be traped, and at least the last one saved.

(It might be easier to "extend the OpenSSL engine API" as @mtrojnar suggested and get OpenSSL to accept the changes. )

Another approach is to use LD_PRELOAD to replace RSA_padding_add_PKCS1_PSS to pass the parameters to populate the CKM_RSA_PKCS_PSS. But this may not work on all OSes.

But to develop this would require a PKCS#11 module that supported PSS in software or hardware.
And it is not clear if this would work.

@mouse07410 how bad do you need this?

mouse07410 2017-10-9
29

允许 CKM_RSA_X_509 (原始 RSA) 用于现有的仅签名密钥将是一个坏主意。

不只是坏-不可能:-)
功能是不可变的。一旦使用一组功能创建了密钥, 它就不能添加或流出任何项。

另一种方法是将 OpenSSL 引擎 API 扩展到可选择的调用其他机制, 如 RSA_PKCS1_PSS_PADDING, 直接从引擎。

有可能发生吗?这个扩展接口有多复杂?

这里是另一种方法, 不需要 OpenSSL mods。当引擎和/或 libp11 看到加密使用 CKM_RSA_X_509, 但 PKCS#11 模块不支持它时, 可以对要加密的块进行检查, 以查看它是否看起来像 RSA_PKCS1_PSS_PADDING。

我喜欢这个主意!

这可能需要实现 ENGINE_set_digests, 以便捕获 M、EM 和哈希。但这需要做之前, 引擎知道这将是一个 PSS 操作, 所以每一个文摘将 traped, 至少最后一个保存。

我能问为什么吗?是防止 OpenSSL 本身在数据上运行哈希来进行签名吗?如果不是-我们可以从机制代码中找出哈希值。

(可能更容易 "扩展 OpenSSL 引擎 API", 如@mtrojnar所建议的那样, 并使 OpenSSL 接受更改。

我不知道这两个部分中的哪一个更可怕。;-)

@mouse07410您需要此操作有多严重?

适度.现在, 它是一个测试设备, 界面和功能仍然没有投在石头上。一旦它已经准备好 "真正的" 评估的人谁可以购买量-我不知道他们的要求是什么...:-(

原文:

Allowing CKM_RSA_X_509 (raw RSA) for existing signature-only keys would be a bad idea.

Not just bad - impossible. :-)
Capabilities are immutable. Once a key has been created with a set of capabilities - it cannot add or shed any.

An alternative approach would be to extend the OpenSSL engine API to optionally invoke additional mechanisms, such as RSA_PKCS1_PSS_PADDING, directly from an engine.

Is it likely to happen? How complicated would this extension interface be?

Here is another approach that does not require OpenSSL mods. When the engine and/or libp11 sees an encryption to use CKM_RSA_X_509 but the PKCS#11 module does not support it, the block to be encrypted could be examined to see if it is looks like RSA_PKCS1_PSS_PADDING.

I like this idea!

This might require implementing ENGINE_set_digests so as to trap M, EM, and Hash. But this would need to be done before the engine knew it would be a PSS operation, so every digest would be traped, and at least the last one saved.

May I ask why? Is it to prevent OpenSSL itself from running the hash over the data to sign? If not - we can figure out the hash from the mechanism code.

(It might be easier to "extend the OpenSSL engine API" as @mtrojnar suggested and get OpenSSL to accept the changes. )

I don't know which of the two parts of the above is scarier. ;-)

@mouse07410 how bad do you need this?

Moderately. Right now it is a beta device, with interface and functionality still not cast in stone. Once it is ready for "real" evaluation by people who can buy in volume - I don't know for sure what their requirements would be... :-(

dengert 2017-10-9
30

你问: "我可以问为什么吗?是防止 OpenSSL 本身在数据上运行哈希来进行签名吗?如果不是-我们可以从机制代码中找出哈希值。

我读 OpenSSL 代码的方式, 哈希是先由 OpenSSL, 然后填充是完成
https://github.com/openssl/openssl/blob/master/crypto/rsa/rsa_pmeth.c中, 行 163-172:

        } else if (rctx->pad_mode == RSA_PKCS1_PSS_PADDING) {
            if (!setup_tbuf(rctx, ctx))
                return -1;
            if (!RSA_padding_add_PKCS1_PSS_mgf1(rsa,
                                                rctx->tbuf, tbs,
                                                rctx->md, rctx->mgf1md,
                                                rctx->saltlen))
                return -1;
            ret = RSA_private_encrypt(RSA_size(rsa), rctx->tbuf,
                                      sig, rsa, RSA_NO_PADDING);

RSA_padding_add_PKCS1_PSS_mgf1创建 tbuf , 然后 RSA_private_encrypt 使用 RSA_private_encryptRSA_NO_PADDING 调用。RSA_PKCS1_PSS_PADDING未传递到引擎。

请注意, engine/libp11 从来没有看到填充 (因此没有 PKCS#11 机制可用), 即使这是一个符号操作, RSA_private_encrypt 被调用做原始的 RSA。

我不清楚, 你可以检查 tbuf, 看看它是否是 PSS, 并得到所有的信息需要传递到 PKCS#11 做 CKM_RSA_PKCS_PSS。最好我可以告诉阅读 RFC 8017, 不能确定数据是否是 PSS pad, 而不知道更多信息。

在你的间谍, 新的 txt 它看起来像 tbuf 将在793行到 795, 但不是所有在跟踪。

103: C_Sign
2017-08-25 18:50:38.254
[in] hSession = 0x7fa60d6041d0
[in] pData[ulDataLen] 00007fa60d6057e0 / 256
    00000000  79 94 00 6E 98 3B AD C7 B8 72 48 B9 33 7E 55 AB  y..n.;...rH.3~U.
    . . . . .
    000000F0  A1 77 86 1D 86 8A 9B 90 CA EE 17 78 5A DA 76 BC  .w.........xZ.v.

最好我可以告诉阅读 RFC 8017, 一个无法确定数据是否为 PSS pad。

原文:

You asked: "May I ask why? Is it to prevent OpenSSL itself from running the hash over the data to sign? If not - we can figure out the hash from the mechanism code."

The way I read the OpenSSL code, the hash is done first by OpenSSL , then the padding is done
in https://github.com/openssl/openssl/blob/master/crypto/rsa/rsa_pmeth.c in lines 163-172:

        } else if (rctx->pad_mode == RSA_PKCS1_PSS_PADDING) {
            if (!setup_tbuf(rctx, ctx))
                return -1;
            if (!RSA_padding_add_PKCS1_PSS_mgf1(rsa,
                                                rctx->tbuf, tbs,
                                                rctx->md, rctx->mgf1md,
                                                rctx->saltlen))
                return -1;
            ret = RSA_private_encrypt(RSA_size(rsa), rctx->tbuf,
                                      sig, rsa, RSA_NO_PADDING);

RSA_padding_add_PKCS1_PSS_mgf1 creates the tbuf, then RSA_private_encrypt is called with RSA_private_encrypt, and RSA_NO_PADDING. The RSA_PKCS1_PSS_PADDING is not passed to the engine.

Note that the engine/libp11 never sees the padding (thus no PKCS#11 mechanism is available) even though this is a sign operation, RSA_private_encrypt is called to do RAW RSA.

It is not clear to me that one could examine the tbuf to see if it is PSS, and get all the info need to pass to PKCS#11 to do CKM_RSA_PKCS_PSS. Best I can tell reading RFC 8017, one can not determine if the data is a PSS pad, without knowing more info.

In your spy-neo.txt it looks like the the tbuf would be in lines 793 to 795, but not all of it in in the trace.

103: C_Sign
2017-08-25 18:50:38.254
[in] hSession = 0x7fa60d6041d0
[in] pData[ulDataLen] 00007fa60d6057e0 / 256
    00000000  79 94 00 6E 98 3B AD C7 B8 72 48 B9 33 7E 55 AB  y..n.;...rH.3~U.
    . . . . .
    000000F0  A1 77 86 1D 86 8A 9B 90 CA EE 17 78 5A DA 76 BC  .w.........xZ.v.

Best I can tell reading RFC 8017, one can not determine if the data is a PSS pad.

mouse07410 2017-10-9
31

我读 OpenSSL 代码的方式, 哈希首先是由 OpenSSL, 然后是做填充..。
最好我可以告诉阅读 RFC 8017, 一个无法确定数据是否为 PSS pad。

恐怕你是100% 对的

这意味着什么?OpenSSL 将不得不对其引擎接口进行更改, 以获得使用组合算法工作的类似 HSM 的设备?

原文:

The way I read the OpenSSL code, the hash is done first by OpenSSL , then the padding is done...
Best I can tell reading RFC 8017, one can not determine if the data is a PSS pad.

I'm afraid you're 100% right.

What are the implications? That OpenSSL would have to make changes to its engine interface to get HSM-like devices that use combined algorithms working?

nmav 2017-10-9
32

如果您通过引擎管理使用 rsa-pss, 并想用 softhsm 测试它, 我已经为它发送了一个修补程序, 用于 rsa-PKCS-pss 机制:
opendnssec/SoftHSMv2#335

原文:

If you manage to use RSA-PSS through the engine and would like to test it with softhsm, I've sent a patch to it for the RSA-PKCS-PSS mechanism:
opendnssec/SoftHSMv2#335

dengert 2017-10-9
33

如果天气转坏, 我不能打高尔夫球下周, 我会看 OpenSSL mods 的引擎。和 libp11/engine 改变使用它。

原文:

If the weather turns bad, and I can't play golf next week, I will look at OpenSSL mods for an engine. and libp11/engine changes to use it.

dengert 2017-10-9
34

@mouse07410 您建议了 PSS 参数的一些缺省值,

RFC 8017、4055和5756和 IEEE Std 1363 a-2004 地址许多这些问题, 包括 ASN. 1 对于这些参数, 它们可以也不能放置在证书和公钥中。

我建议默认值应基于这些 rfc。

我只瞥了一眼这些 rfc 和 OpenSSL 代码, 看看他们是否同意。我确实看到 OpenSSL 代码有 i2d_RSA_PSS_PARAMS 和 d2i_RSA_PSS_PARAMS。但没有看到他们在哪里使用或如果他们遵循这些 rfc。

我希望您能够查看这些 rfc, 并建议默认值应基于 rfc。

我将继续研究 OpenSSL mods, 将 PSS 参数传递给引擎。

原文:

@mouse07410 You had suggested some defaults for the PSS parameters,

RFC 8017, 4055 and 5756 and IEEE Std 1363a-2004 address many of these issue, and include ASN.1 for the parameters are where they can and can not be placed in certificates and public keys.

I would suggest that the defaults should be based on these RFCs.

I have only glanced at these RFCs and the OpenSSL code to see if they agree. I do see that the OpenSSL code has i2d_RSA_PSS_PARAMS and d2i_RSA_PSS_PARAMS. but have not looked to see where they are used or if they follow these RFCs.

I would hope you would review these RFC and would suggest that the defaults should be based on the RFCs.

I am continuing to look at OpenSSL mods to pass the PSS parameters to an engine.

mouse07410 2017-10-9
35

我将继续研究 OpenSSL mods, 将 PSS 参数传递给引擎。

@dengert感谢您对此的调查。

我认为的真正诀窍是将 PSS 方法和参数发送到引擎时, 基础令牌支持它, 并执行 OpenSSL 正在做的事情。因为一方面, 我想看到像 YubiHSM2 支持直接由 OpenSSL (与引擎) 的设备-但另一方面, 我会的如果这种支持的代价是能够在像 Yubikey 和 CAC 这样的令牌上进行 RSA PSS, 那只能做原始 RSA (aka RSA-X-509 )。

RFC 8017、4055和5756和 IEEE Std 1363 a-2004 地址许多这些问题..。

好的, 我将检查 RFC 8017、4055和5756。也可以检查 IEEE Std 1363-2004-没有承诺在这里。

我建议默认值应该基于这些 rfc.....。我希望您能够查看这些 rfc, 并建议默认值应基于 rfc。

如果这些 rfc 和 OpenSSL 之间存在分歧, 我建议遵循事实上的标准 (aka OpenSSL), 而不是 "纸本位"。但我希望他们能配合会在这里报告。

原文:

I am continuing to look at OpenSSL mods to pass the PSS parameters to an engine.

@dengert thank you for looking into this.

The real trick in my opinion is sending PSS method and parameters to the engine when the underlying token supports it, and doing what OpenSSL is doing now when it doesn't. Because on the one hand I'd love to see devices like YubiHSM2 supported directly by OpenSSL (with engines) - but on the other hand I'd really hate if that support came at the cost of being able to do RSA-PSS on tokens like Yubikey and CAC that can only do the raw RSA (aka RSA-X-509).

RFC 8017, 4055 and 5756 and IEEE Std 1363a-2004 address many of these issues...

OK, I'll check the RFC 8017, 4055 and 5756. Might also check IEEE Std 1363a-2004 - no promise here.

I would suggest that the defaults should be based on these RFCs. ... I would hope you would review these RFC and would suggest that the defaults should be based on the RFCs.

If there's disagreement between these RFCs and OpenSSL, I'd suggest following the de-facto standard (aka OpenSSL) than the "paper standard". But apriori I'd expect them to match. Will report here anyway.

dengert 2017-10-9
36

您使用的 YubiHSM2, 与他们的 PKCS#11 模块。该模块表示该设备不支持 RAW, 但事实果真如此吗?他们实际做的 PSS 是软件而不是 HSM 吗?如果是这样, 设备是没有更好的, 然后是一个智能卡, 做 RSA_RAW。
pcscd 跟踪显示什么?
他们使用安全通道吗?

原文:

You have been using the YubiHSM2, with their PKCS#11 module. The module says the device does not support RAW, but is that really the case? Are they actually doing the PSS is software rather than on the HSM? If they are then the device is no better then a smart card that does RSA_RAW.
What does a pcscd trace show?
Do they use some secure channel?

mouse07410 2017-10-9
37

您使用的 YubiHSM2, 与他们的 PKCS#11 模块。

是的。请注意, 两者都是 "beta", 这意味着它们在进入生产之前可以显著改变。

该模块表示该设备不支持 RAW, 但事实果真如此吗?

AFAIK, 是的。测试自己, 并验证与开发商。开发人员实际上拒绝为原始模式添加支持, 理由是安全考虑。

他们实际做的 PSS 是软件而不是 HSM 吗?

AFAIK, 不他们在 hsm 上做 pss, 并且他们的软件都将默认的 pss 参数 (与 OpenSSL 兼容) 发送到 hsm。我通过在 HSM 上使用它们的工具创建一个 RSA-PSS 签名来验证兼容性, 并使用 OpenSSL 验证它。

HSM 将不变的 "功能" 附加到它生成或存储的每个键上。这些功能定义了允许此密钥执行的签名类型 (尝试违反这些操作的行为-失败)。

pcscd 跟踪显示什么?

没有。

他们使用安全通道吗?

我认为如此。他们的软件 (连接器) 和设备之间的通信被加密。

但同样, 他们的智能卡 (令牌) 和这个设备之间的一个可观察的区别是: 他们的智能卡只做原始的 RSA, 并且要求 PSS 和 OAEP 由呼叫软件完成。他们的 HSM2 设备完全执行原始的 RSA, 而且只有 PSS 和 OAEP (和 PKCS1 v1.5)。

原文:

You have been using the YubiHSM2, with their PKCS#11 module.

Yes. Note that both are "beta", meaning they can change significantly before entering production.

The module says the device does not support RAW, but is that really the case?

AFAIK, yes it is. Tested myself, and verified with the developers. The developers actually refused to add support for the raw mode, citing security considerations.

Are they actually doing the PSS is software rather than on the HSM?

AFAIK, no. They do PSS on the HSM, and all that their software does it sending the default PSS parameters (compatible with OpenSSL) to the HSM. I validated the compatibility by creating an RSA-PSS signature on the HSM with their tools, and validating it with OpenSSL.

HSM attaches immutable "capabilities" to each key it generates or stores. Those capabilities define what kind of signature this key is allowed to perform (operations that try to violate those - fail).

What does a pcscd trace show?

Don't have it.

Do they use some secure channel?

I think so. Traffic between their software (connector) and the device is encrypted.

But again, one observable difference between their smart cards (tokens) and this device is: their smart cards do only raw RSA, and require PSS and OAEP done by the calling software. Their HSM2 device does not do raw RSA at all, and only does PSS and OAEP (and PKCS1 v1.5).

dengert 2017-10-9
38

我想如果 OpenSSL 愿意加入 RSA_METHOD

  int (*rsa_sign_ctx) (int type,
                     const unsigned char *m, unsigned int m_length,
                     unsigned char *sigret, unsigned int *siglen,
                     const RSA *rsa, EVP_PKEY_CTX *rctx);

并把它在 rsa_pmethod 的正确位置. c 然后引擎就可以访问 PSS 所需的所有 it。
它可以返回, 继续做旧的方式: 在软件中进行填充和调用 (* rsa_sign) 或在引擎中执行整个符号操作, coiuld 将 PSS 参数传递给 PKCS#11。
我还在看代码。

主要问题是 EVP_PKEY_CTX 没有传递给引擎。

原文:

I think if OpenSSL was willing to add to the RSA_METHOD

  int (*rsa_sign_ctx) (int type,
                     const unsigned char *m, unsigned int m_length,
                     unsigned char *sigret, unsigned int *siglen,
                     const RSA *rsa, EVP_PKEY_CTX *rctx);

And called it at the right place in rsa_pmethod.c then the engine would have access to all it needs for PSS.
It could return, continue doing the old way: do the padding in software and call (*rsa_sign) or do the whole sign operation within the engine which coiuld be pass the PSS parameter to PKCS#11.
I a still looking at the code.

The main problem is the EVP_PKEY_CTX is not passed to an engine.

mouse07410 2017-10-9
39

已检查 RFC 8017。它不强制默认值, 只有建议它们:

  • 对于盐长度, 它说, 应用程序通常使用 hLen 或0。
  • 对于 MGF, 他们说, 他们建议使用与消息相同的哈希值, 也就是说, 对于 SHA512-RSA-PKCS-PSS MGF1 将使用 SHA512 (和不是SHA-1)。

这些是唯一有问题的参数, AFAIK。

RFC 4055 现在是相当日期。它同意salt问题。关于哈希, 它说一个必须支持 SHA-1 (即 SHA1-RSA-PKCS-PSS ), 并且可以支持其他哈希函数。

我建议坚持与 RFC 8017, 是更多的电流。

原文:

Checked RFC 8017. It does not force default values, it only recommends them:

  • for salt length it says that applications usually use hLen or 0.
  • for MGF they say they recommend using the same hash as for the message, i.e., for SHA512-RSA-PKCS-PSS MGF1 would use SHA512 (and not SHA-1).

These are the only parameters in question, AFAIK.

RFC 4055 is pretty dated now. It concurs with salt Len issue. Regarding hash - it says that one must support SHA-1 (i.e., SHA1-RSA-PKCS-PSS), and may support other hash functions.

I suggest sticking with RFC 8017, being more current.

dengert 2017-10-9
40

我看了 OpenSSL-1.1. 0 f, 主要问题是 rsa_pmeth. c 在 pkey_rsa_sign () 中, 不给引擎机会查看 RSA_PSS 参数并在内部进行填充, 然后进行以下操作:
178 RSA_private_encrypt (RSA_size (RSA), rctx-> tbuf,
179 sig, rsa, RSA_NO_PADDING);

因而对引擎它似乎是一些数据的 RSA 原始的操作。

我附上一些 mods 到 OpenSSL-1.1. 0 f, 添加 (* rsa_sign_evp_pkey_ctx) RSA_METHOD 及其相关的功能和定义。

另外附上是一个概念的证明为 pkcs11_rsa_sign_evp_pkey_ctx_method 在 p11_rsa. c 打印参数到 stderr, 然后返回让 OpenSSL 做什么它现在在软件。

对于不支持 CKM_RSA_X_509 的标记, 可以从 PSS 参数、哈希、哈希大小和密钥大小派生出一个机制。如果令牌可以做机制 PKCS#11 将被调用做它和结果返回。(我会把这个留给别人。

最大的问题将是让 OpenSSL 接受这些 mods 或提供他们自己的 mods 来解决问题。

没有试图看看这是否会在任何其他版本的 OpenSSL。
如果 OpenSSL 对这些 mods 不感兴趣, 我不想再去了。

我要求 OpenSC/libp11 开发人员在我提交这个问题和解决方案之前, 先看看他的 OpenSSL。如果它看起来有希望, libp11 代码的一个完整功能的版本与一个真正的令牌将有很长的路要去帮助说服 OpenSSL 有一个问题和解决方案。

rsa_sign_evp_pkey_ctx-1. txt
pkcs11_rsa_sign_evp_pkey_ctx_method-1. txt

原文:

I have looked at OpenSSL-1.1.0f and the main problem is rsa_pmeth.c in pkey_rsa_sign(), does not give the engine a chance to see the RSA_PSS parameters and does padding internally then does:
178 ret = RSA_private_encrypt(RSA_size(rsa), rctx->tbuf,
179 sig, rsa, RSA_NO_PADDING);

Thus to the engine it appears to be an RSA RAW operation of some data.

I am attaching some mods to OpenSSL-1.1.0f that add (*rsa_sign_evp_pkey_ctx) to the RSA_METHOD and its related functions and definitions.

Also attached is a proof of concept for a pkcs11_rsa_sign_evp_pkey_ctx_method in p11_rsa.c that prints the parameters to stderr, then returns to let OpenSSL do what it does now in software.

For a token that does not support CKM_RSA_X_509 a mechanism could be derived from PSS parameters, hash, hash size and key size. If the token can do the mechanism PKCS#11 would be called to do it and the results returned. (I will leave this up to someone else.)

The biggest problem will getting OpenSSL to accept these mods or provide their own mods to get around the problem.

No attempt was made to see if this would work in any other version of OpenSSL.
I don't want to go any further if OpenSSL is not interested in these mods.

I am asking the OpenSC/libp11 developers to look his over before I submit this problem and solution to OpenSSL. If it looks promising, a full functioning version of the libp11 code with a real token would go a long way to help convince OpenSSL there is a problem and a solution.

rsa_sign_evp_pkey_ctx-1.txt
pkcs11_rsa_sign_evp_pkey_ctx_method-1.txt

mouse07410 2017-10-9
41

@dengert这是一个很好的开始。不幸的是, 它还没有奏效。由于某种原因, 它仍然将 RSA-X-509 命令发送到引擎。

我应用了两个补丁。OpenSSL 有一个问题 (我是手动纠正的):

cat util/libcrypto.num.rej
***************
*** 4230,4232 ****
  UINT32_it                               4214	1_1_0f	EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:
  ZINT64_it                               4215	1_1_0f	EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:
  ZINT64_it                               4215	1_1_0f	EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:
--- 4230,4234 ----
  UINT32_it                               4214	1_1_0f	EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:
  ZINT64_it                               4215	1_1_0f	EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:
  ZINT64_it                               4215	1_1_0f	EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:
+ RSA_meth_set_sign_evp_pkey_ctx          4216    1_1_0f  EXIST::FUNCTION:RSA
+ RSA_sign_evp_pkey_ctx                   4217    1_1_0f  EXIST::FUNCTION:RSA
$ 

请注意, 我保留的 OpenSSL-1.1 版本是 OpenSSL_1_1_0-stable , 但它不能与1.1.0f 相差太多, 以致于使修补程序无效。

$ ~/openssl-1.1/bin/openssl dgst -engine pkcs11 -keyform engine -sha384 -sign "pkcs11:token=YubiHSM;id=%03%01;type=private" -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:-1 -out ~/src/t3072.dat.sigpss ~/src/t3072.dat
engine "pkcs11" set.
Enter PKCS#11 token PIN for YubiHSM:
 pkcs11_rsa_sign_ctx_method called
RSA_PSS
saltlen=48 sigmd=673 mdf1=673 
Error Signing Data
140736009962432:error:8207A070:PKCS#11 module:pkcs11_private_encrypt:Mechanism invalid:p11_rsa.c:120:
$ 

这里的间谍节录:

. . . . .
151: C_GetAttributeValue
2017-09-12 15:05:06.964
[in] hSession = 0x0
[in] hObject = 0x30301
[in] pTemplate[1]:
    CKA_ALWAYS_AUTHENTICATE  00007fc0f16366d0 / 1
[out] pTemplate[1]:
    CKA_ALWAYS_AUTHENTICATE  False
Returned:  0 CKR_OK
 pkcs11_rsa_sign_ctx_method called
RSA_PSS
saltlen=48 sigmd=673 mdf1=673

152: C_SignInit
2017-09-12 15:05:06.964
[in] hSession = 0x0
pMechanism->type=CKM_RSA_X_509
[in] hKey = 0x30301
Returned:  112 CKR_MECHANISM_INVALID
Error Signing Data
140736009962432:error:8207A070:PKCS#11 module:pkcs11_private_encrypt:Mechanism invalid:p11_rsa.c:120:

153: C_CloseSession
2017-09-12 15:05:06.965
[in] hSession = 0x0
Returned:  0 CKR_OK

这里是完整的间谍:
dengert-spy1

令牌本身使用 SHA384-RSA-PSS 的符号很好:

$ yhsm2-tool -s -m SHA384-RSA-PKCS-PSS --id 0301 -i ~/src/t3072.dat -o ~/src/t3072.dat.sigpss-opensc
Using slot 0 with a present token (0x0)
Logging in to "YubiHSM".
Please enter User PIN: 
Using signature algorithm SHA384-RSA-PKCS-PSS
PSS parameters: hashAlg=SHA384, mgf=MGF1-SHA384, salt=48 B
$ ~/openssl-1.1/bin/openssl dgst -engine pkcs11 -keyform engine -sha384 -verify "pkcs11:token=YubiHSM;id=%03%01;type=public" -sigopt rsa_padding_mode:pss -signature ~/src/t3072.dat.sigpss-opensc ~/src/t3072.dat
engine "pkcs11" set.
Enter PKCS#11 token PIN for YubiHSM:
Verified OK
$

yhsm2-tool 只是一个别名pkcs11-tool --module /usr/local/lib/yubihsm_pkcs11.0.1.0.dylib --login

原文:

@dengert it's a very good start. Unfortunately, it didn't work yet. For some reason it still sends RSA-X-509 command down to the engine.

I applied both patches. The one for OpenSSL had a problem (which I remedied manually):

cat util/libcrypto.num.rej
***************
*** 4230,4232 ****
  UINT32_it                               4214	1_1_0f	EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:
  ZINT64_it                               4215	1_1_0f	EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:
  ZINT64_it                               4215	1_1_0f	EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:
--- 4230,4234 ----
  UINT32_it                               4214	1_1_0f	EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:
  ZINT64_it                               4215	1_1_0f	EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:
  ZINT64_it                               4215	1_1_0f	EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:
+ RSA_meth_set_sign_evp_pkey_ctx          4216    1_1_0f  EXIST::FUNCTION:RSA
+ RSA_sign_evp_pkey_ctx                   4217    1_1_0f  EXIST::FUNCTION:RSA
$ 

Note that the OpenSSL-1.1 version I keep is OpenSSL_1_1_0-stable, but it cannot differ so much from 1.1.0f as to invalidate your patch.

$ ~/openssl-1.1/bin/openssl dgst -engine pkcs11 -keyform engine -sha384 -sign "pkcs11:token=YubiHSM;id=%03%01;type=private" -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:-1 -out ~/src/t3072.dat.sigpss ~/src/t3072.dat
engine "pkcs11" set.
Enter PKCS#11 token PIN for YubiHSM:
 pkcs11_rsa_sign_ctx_method called
RSA_PSS
saltlen=48 sigmd=673 mdf1=673 
Error Signing Data
140736009962432:error:8207A070:PKCS#11 module:pkcs11_private_encrypt:Mechanism invalid:p11_rsa.c:120:
$ 

Here's the SPY excerpt:

. . . . .
151: C_GetAttributeValue
2017-09-12 15:05:06.964
[in] hSession = 0x0
[in] hObject = 0x30301
[in] pTemplate[1]:
    CKA_ALWAYS_AUTHENTICATE  00007fc0f16366d0 / 1
[out] pTemplate[1]:
    CKA_ALWAYS_AUTHENTICATE  False
Returned:  0 CKR_OK
 pkcs11_rsa_sign_ctx_method called
RSA_PSS
saltlen=48 sigmd=673 mdf1=673

152: C_SignInit
2017-09-12 15:05:06.964
[in] hSession = 0x0
pMechanism->type=CKM_RSA_X_509
[in] hKey = 0x30301
Returned:  112 CKR_MECHANISM_INVALID
Error Signing Data
140736009962432:error:8207A070:PKCS#11 module:pkcs11_private_encrypt:Mechanism invalid:p11_rsa.c:120:

153: C_CloseSession
2017-09-12 15:05:06.965
[in] hSession = 0x0
Returned:  0 CKR_OK

Here's the full SPY:
dengert-spy1.txt

The token itself signs fine using SHA384-RSA-PSS:

$ yhsm2-tool -s -m SHA384-RSA-PKCS-PSS --id 0301 -i ~/src/t3072.dat -o ~/src/t3072.dat.sigpss-opensc
Using slot 0 with a present token (0x0)
Logging in to "YubiHSM".
Please enter User PIN: 
Using signature algorithm SHA384-RSA-PKCS-PSS
PSS parameters: hashAlg=SHA384, mgf=MGF1-SHA384, salt=48 B
$ ~/openssl-1.1/bin/openssl dgst -engine pkcs11 -keyform engine -sha384 -verify "pkcs11:token=YubiHSM;id=%03%01;type=public" -sigopt rsa_padding_mode:pss -signature ~/src/t3072.dat.sigpss-opensc ~/src/t3072.dat
engine "pkcs11" set.
Enter PKCS#11 token PIN for YubiHSM:
Verified OK
$

yhsm2-tool is merely an alias for pkcs11-tool --module /usr/local/lib/yubihsm_pkcs11.0.1.0.dylib --login

dengert 2017-10-9
42

不知道为什么它会拒绝补丁, 其他则更改是最后2行。

正如我所说: "也附上了一个的概念证明的 pkcs11_rsa_sign_evp_pkey_ctx_method 在 p11_rsa. c 将参数打印到 stderr, 然后返回, 让 OpenSSL 做它现在在软件。

它显示 OpenSSL 可以传入 PSS 参数。现在只打印出来

我希望@mouse07410@mtrojnar@Jakuje或其他人将添加 libp11 代码以测试卡是否只能在带有所选哈希的卡上进行 RSA_PSS, 然后使用参数填充
一个 CK_RSA_PKCS_PSS_PARAMS and CK_MECHANISM 指向它并调用 C_SignInit, 然后将结果传回。

原文:

Don't know why it would reject the patch, other then the changes are the last 2 lines.

As I said: "Also attached is a proof of concept for a pkcs11_rsa_sign_evp_pkey_ctx_method in p11_rsa.c that prints the parameters to stderr, then returns to let OpenSSL do what it does now in software."

It shows OpenSSL can pass in the PSS parameters. It only prints them for now.

I expect @mouse07410 , @mtrojnar , @Jakuje or someone would add the libp11 code to test if the card could only do RSA_PSS with on the card with the selected hash, then use the parameters to fill in
a CK_RSA_PKCS_PSS_PARAMS and CK_MECHANISM pointing to it and call C_SignInit, then pass back the results.

mouse07410 2017-10-9
43

正如我所说: "也附上了一个概念证明..。

织补..。我误解了...:-(

那么大部分的丢失的东西是在 libp11 样本?它需要检查令牌的功能, 或者继续使用 PSS, 或者只是返回让 OpenSSL 在软件中做它的事情?

原文:

As I said: "Also attached is a proof of concept for...

Darn... I misunderstood... :-(

So the bulk of the missing stuff is in the libp11 sample? It's there where it needs to check the token's capabilities, and either proceed with PSS, or just return to let OpenSSL do its thing in software?

dengert 2017-10-9
44

正确.我想所有丢失的代码都在 libp11。

从参数中确定使用了什么哈希值, 并从关键字 RSA_size。

可能也需要这些:
PKCS11_KEY * 键 = RSA_get_ex_data (RSA, rsa_ex_index);
PKCS11_SLOT * 插槽 = KEY2SLOT (键);
PKCS11_CTX * 酰 = KEY2CTX (键);
PKCS11_KEY_private * kpriv = PRIVKEY (键);
PKCS11_SLOT_private * spriv = PRIVSLOT (插槽);
CK_MECHANISM 机制;

您还将定义 CK_RSA_PKCS_PSS_PARAMS , 我认为是在@Jakuje
OpenSC/OpenSC#1146
它更新 pkcs11 以添加 CK_RSA_PKCS_PSS_PARAMS 和其他标志。

告诉你, 如果你不走得太远, 我会在几天内看看。

原文:

Correct. I think all the missing code is in libp11.

Determine from the parameters the what hash was used, and from the key what is RSA_size.

Probable also need these:
PKCS11_KEY *key = RSA_get_ex_data(rsa, rsa_ex_index);
PKCS11_SLOT *slot = KEY2SLOT(key);
PKCS11_CTX *ctx = KEY2CTX(key);
PKCS11_KEY_private *kpriv = PRIVKEY(key);
PKCS11_SLOT_private *spriv = PRIVSLOT(slot);
CK_MECHANISM mechanism;

You will also the defination of the CK_RSA_PKCS_PSS_PARAMS which I think was in @Jakuje
OpenSC/OpenSC#1146
it updates pkcs11.h to add CK_RSA_PKCS_PSS_PARAMS and other flags.

Tell you what, if you don't get very far, I will look at in a few days.

mtrojnar 2017-10-9
45

我审阅了@dengert提交的 OpenSSL 修补程序。 提出的解决方案简单灵活。 我喜欢它确保向后兼容性的方式。

我注意到在向 OpenSSL 提交公关之前需要解决的一些琐碎问题:

  • RSA_sign_evp_pkey_ctx()被声明和导出, 但从未实现。 我想这个函数是不需要的。
  • rsa_verify_evp_pkey_ctx方法也应该添加, 即使它对 libp11 是无用的。
  • PSS 应该仅仅是一个例子 (如果有的话), 因为建议的更改对其他填充也很有用。
  • 缩进: OpenSSL 使用4空格。
  • 错别字: "有用", "兼容性"。
原文:

I reviewed the OpenSSL patch submitted by @dengert. The proposed solution is simple and flexible. I love the way it ensures backward compatibility.

I noticed a few trivial issues that need to be addressed before submitting a PR to OpenSSL:

  • RSA_sign_evp_pkey_ctx() is declared and exported, but it is never implemented. I guess there is no need for this function.
  • rsa_verify_evp_pkey_ctx method should also be added, even though it is not useful for libp11.
  • PSS should probably only be mentioned as an example (if at all), as the proposed change is also useful for other paddings.
  • Indentation: OpenSSL uses 4 spaces.
  • Typos: "Usefull", "compatability".
mouse07410 2017-10-9
46

@mtrojnar谢谢!
@dengert看起来这个调用也可以用于 OAEP, 对吗?让我们更新它?

原文:

@mtrojnar thank you!
@dengert it looks like this call can be used for OAEP as well, right? Let's update it so?

dengert 2017-10-9
47
原文:
mouse07410 2017-10-9
48

所有这些变化都是为 OpenSSL-1.1 +, 正确?因此, 在 libp11 代码中, 我添加了 OpenSSL 版本 > = 比1.1.0 后卫。

原文:

All these changes are for OpenSSL-1.1+, correct? So in the libp11 code I'm adding guards for OpenSSL version >= than 1.1.0.

dengert 2017-10-9
49

记住, 这是一个概念的证明。 我只看了1.1.0。它看起来就像没有必要的 OpenSSL mods。p11_rsa 的 mods 也会看起来不同。所以不要做任何这一切。

原文:

Remember this was a proof of concept. I only looked at 1.1.0. And it looks like there will be no need for OpenSSL mods. The p11_rsa.c mods will look different too. So don't commit any of this.

mouse07410 2017-10-9
50

p11_rsa 的 mods 也会看起来不同。所以不要做任何这一切。

太迟了。;-)

但我确信 (至少我希望;)我将能够恢复这些提交。

附注 OpenSSL-1.1. 1-正在进行的不具有文件 crypto/rsa/rsa_null.c

原文:

The p11_rsa.c mods will look different too. So don't commit any of this.

Too late. ;-)

But I'm sure (or at least I hope ;) I'll be able to revert those commits.

P.S. OpenSSL-1.1.1-devel does not have file crypto/rsa/rsa_null.c any more.

dengert 2017-10-9
51

这里是一个新版本的概念证明 RSA-PSS 要做的卡。因为我没有这些卡, 你需要填写 PKCS#11。Itr 替换以前的更改, 并重命名该例程。

不需要更改 openssl。
看到:
https://github.com/dengert/libp11/tree/rsa-pss-2

这是不完整的, 需要 PKCS#11 代码添加到它。
要使 OAEP 填充工作, 需要创建一个例程 (类似 pkcs11_pkey_rsa_sign, 而不是 pkey_rsa_sign) pkcs11_pkey_rsa_encrypt, 以取代 pkey_rsa_encrypt。

原文:

Here is a new version of the proof of concept for RSA-PSS to be done on card. Since I don' t have one of these cards, you will need to fill in the PKCS#11. Itr replaces the previous changes, and renames the routine.

No changes are needed to openssl.
See:
https://github.com/dengert/libp11/tree/rsa-pss-2

This is not complete, and needs PKCS#11 code added to it.
To get OAEP padding to work, a routine (similar the pkcs11_pkey_rsa_sign which is called instead of pkey_rsa_sign) pkcs11_pkey_rsa_encrypt needs to be created which would replace pkey_rsa_encrypt.

mtrojnar 2017-10-9
52

在引擎代码中放一半实现的原因是我无法理解的。 此功能在直接使用 libp11 的应用程序中是否也有用, 而不是通过引擎?

原文:

The reason to put half of the implementation in the engine code is beyond my comprehension. Wouldn't this feature be also useful in applications that use libp11 directly, and not via the engine?

dengert 2017-10-9
53

这是一个例子, 一个概念的证明, 引擎提供的方法例程可以获得的 PSS 参数 OpenSSL 已设置。没有添加用于实际使用 PKCS#11 的 PSS 参数的代码。 对于不支持 CKM_RSA_X_509 的设备, 这是必需的, 但可以支持 CKM_RSA_PKCS_PSS。

我的全部工作是了解如何获取参数, 并让 OpenSSL 调用一个可以调用 C_SignInit 的例程。 我叫她 pkcs11_pkey_rsa_sign 。该名称的选择可能是误导, 它可以改名, 它可以从 p11_rsa。

当调用 pkcs11_pkey_rsa_sign 时, tbs 是消息的哈希值。 填充和加密尚未完成。 如果 pkcs11_pkey_rsa_sign 不执行任何工作, 则需要调用 original_pkey_rsa_sign , 这将以旧方式执行某些事情。 (OpenSSL 也有一些可以被钩住的消化方法, 如果需要, CKM__RSA_PKCS_PSS 也可以支持。

请随时做任何你想要的代码和添加 PKCS#11 代码, 可以直接使用的 libp11。pkcs11_pkey_rsa_sign然后可以调用此 libp11 代码。

OpenSC/OpenSC#1146更新 OpenSC 的 pkcs11. h 的版本, 并从 OpenSSL 到 PSS 和 pkcs11 工具中的示例进行了大量的映射例程. 需要的 PKCS#11 呼叫的 c。

原文:

This was an example, a proof of concept that an engine provided METHOD routine could get access to the PSS parameters OpenSSL had set. No code was added to actually use the PSS parameters with PKCS#11. This is needed for devices that do not support CKM_RSA_X_509, but could support CKM_RSA_PKCS_PSS.

My whole effort was to find out how to get access to the parameters and have OpenSSL call a routine that could call C_SignInit. I called that pkcs11_pkey_rsa_sign. The choice of that name may be misleading and it could be renamed and it could be moved from p11_rsa.c.

When pkcs11_pkey_rsa_sign is called, the tbs is the hash of the message. The padding and crypto has not been done. If pkcs11_pkey_rsa_sign does not do anything, then it needs to call the original_pkey_rsa_sign, which will do things the old way. (OpenSSL also has some digest methods that could also be hooked so CKM__RSA_PKCS_PSS could also be supported if needed.)

Please feel free to do whatever you want with the code and to add the PKCS#11 code that could be used directly by libp11. pkcs11_pkey_rsa_sign could then call this libp11 code.

OpenSC/OpenSC#1146 updates OpenSC's version of pkcs11.h and has a number of mapping routines from OpenSSL to PSS and examples in pkcs11-tool.c of the PKCS#11 calls needed.

mouse07410 2017-10-9
54

@dengert我相信, 在这个线程上的其他人的帮助和帮助下, 我得到了 rsa-PSS (感谢@Jakuje) 和 rsa-OAEP 完全操作。据我所知, 所有的功能/选项都经过了测试。可以随时查看我的

@mtrojnar如果您能够帮助您将这些功能导入, 那就太好 libp11 了。我不知道 libp11.dylib 的详细信息, 也不了解当前正在使用它的应用程序。因此, 我无法对所请求的功能是否属于引擎本身或 libp11 库的讨论作出贡献。但是, 无论你认为它适合 best-it 将是伟大的, 如果你可以添加它 (基于中的工作代码 pkcs11-tool.c 和概念的证明@dengert

谢谢!

原文:

@dengert I believe that with your help and help of the others on this thread I've got RSA-PSS (thanks @Jakuje!) and RSA-OAEP fully operational. As far as I can tell, all the capabilities/options have been tested. Feel free to take a look at my master.

@mtrojnar it would be great if you could help getting these capabilities into libp11. I don't know the details of libp11.dylib, and have no idea what applications currently are using it. So I cannot contribute to the discussion whether the requested functionality belongs to the engine itself, or to the libp11 library. But wherever you think it fits best - it would be great if you could add it (based on the working code in pkcs11-tool.c and the proof of concept by @dengert .

Thanks!

mtrojnar 2017-10-9
55

@mouse07410我很感激你的好意来分配我的时间来实现你所需要的功能。

原文:

@mouse07410 I appreciate your kind offer to allocate my time to implement the feature you need.

mouse07410 2017-10-9
56

@mtrojnar我只是要求你的帮助, 因为 (a) 你保持 libp11 和 (b) 你知道它比 (例如) 我做。

至于功能 "我需要"-我敢肯定, 我是唯一一个谁会希望使用 OpenSSL 来执行由 HSM 设备支持的操作。

我很乐意增强@dengert的概念证明, 使其完全可用 (通过添加在 pkcs11 工具中工作的代码)-但您似乎不满意它的设计方式 (不提供其他示例)???

原文:

@mtrojnar I'm simply asking for your help since (a) you maintain libp11 and (b) you know it better than (for example) I do.

As for the feature "I need" - I'm sure I'm the only one who'd ever want to use OpenSSL to perform operations backed by an HSM device.

I'd be happy to enhance @dengert 's proof of concept to make it fully-capable (by adding the code that worked in pkcs11-tool.c) - but you seemed unhappy with how it was designed (without offering an alternative example)???

mtrojnar 2017-10-9
57

坏消息是, 虽然我确实目前协调社区的努力, 以改善 libp11, 我的空余时间不是无限的。
好消息是, 我肯定不是唯一能够添加您要求的功能的开发人员。
您是否建议 libp11 在其当前状态下不允许使用 OpenSSL 来执行由 HSM 设备支持的操作?

原文:

Bad news is that although I indeed currently coordinate community efforts to improve libp11, my spare time is not unlimited.
Good news is I am certainly not the only developer capable of adding the feature you requested.
Are you suggesting that libp11 in its current state does not allow to use OpenSSL to perform operations backed by an HSM device?

mouse07410 2017-10-9
58

@dengert谢谢!!我想我现在已经足够开始添加 RSA OAEP 支持了。

@mtrojnar您是否愿意将 RSA-PSS 代码 (或多或少) 合并到当前在我的 libp11 叉 (rsa-pss-2 分支) 中的方式?如果没有-需要改变什么?

与其让 orig_rsa_pkey_sign()extern 看起来导致某些编译器和链接问题, 不如将它挂在 st_engine_ctx 的引擎中, 并定义一个函数来获取它。

@mtrojnar您认为@dengert将函数指针添加到结构的建议是什么 st_engine_ctx ?你同意还是反对?我宁愿现在就学你的意见。

原文:

@dengert thank you!! I think I have enough now to start adding RSA-OAEP support.

@mtrojnar are you willing to merge the RSA-PSS code (more-or-less) the way it currently is in my libp11 fork (rsa-pss-2 branch)? If not - what needs to be changed?

Rather than having the orig_rsa_pkey_sign() by an extern that appears to cause some compiler and linking issues, maybe it could be hung off the engine in st_engine_ctx and a function defined to get it.

@mtrojnar what do you think of @dengert 's suggestion to add the function pointers to st_engine_ctx structure? Are you OK with it, or against it? I'd rather learn your opinion now.

mouse07410 2017-10-9
59

初步结果

rsa-OAEP 代码与 HSM 设备一起工作, 但为 Yubikey 新 (仅用于原始 rsa) 的 OAEP 中断了 rsa。有趣的是, 崩溃发生在 OpenSSL 本身, 不仅在解密尝试, 而且还在尝试加密

$  ~/openssl-1.1/bin/openssl pkeyutl -engine pkcs11 -keyform engine -encrypt -pubin -inkey "pkcs11:token=Uri%20the%20Great;id=%03;type=public" -in t256.txt -out t256.txt.oaep3 -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha512 
engine "pkcs11" set.
Segmentation fault: 11
$ openssl pkeyutl -engine pkcs11 -keyform engine -encrypt -pubin -inkey "pkcs11:token=Uri%20the%20Great;id=%03;type=public" -in t256.txt -out t256.txt.oaep3 -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha512
engine "pkcs11" set.
$ openssl pkeyutl -engine pkcs11 -keyform engine -decrypt -inkey "pkcs11:token=Uri%20the%20Great;id=%03;type=private" -in t256.txt.oaep3 -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha512
engine "pkcs11" set.
Enter PKCS#11 token PIN for Uri the Great:
12345678901234567890123456789012     # good output
$ ~/openssl-1.1/bin/openssl pkeyutl -engine pkcs11 -keyform engine -decrypt -inkey "pkcs11:token=Uri%20the%20Great;id=%03;type=private" -in t256.txt.oaep3 -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha512
engine "pkcs11" set.
Enter PKCS#11 token PIN for Uri the Great:
RSA_OAEP
hashAlg=SHA384 mgf=MGF1-SHA512 
Segmentation fault: 11
$

以下是加密崩溃:

Exception Type:        EXC_BAD_ACCESS (SIGSEGV)
Exception Codes:       KERN_INVALID_ADDRESS at 0x0000000000000000
Exception Note:        EXC_CORPSE_NOTIFY

Termination Signal:    Segmentation fault: 11
Termination Reason:    Namespace SIGNAL, Code 0xb
Terminating Process:   exc handler [0]

VM Regions Near 0:
--> 
    __TEXT                 000000010f20b000-000000010f26d000 [  392K] r-x/rwx SM=COW  /Users/USER/*

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   libcrypto.1.1.dylib           	0x000000010f3555c8 BN_bn2bin + 136
1   libcrypto.1.1.dylib           	0x000000010f45cfb2 rsa_ossl_public_encrypt + 866
2   libcrypto.1.1.dylib           	0x000000010f45f23d pkey_rsa_encrypt + 205
3   openssl                       	0x000000010f22d37d pkeyutl_main + 3053
4   openssl                       	0x000000010f2261c6 do_cmd + 134
5   openssl                       	0x000000010f226132 main + 1186
6   libdyld.dylib                 	0x00007fffd0910235 start + 1

这是解密崩溃:

Exception Type:        EXC_BAD_ACCESS (SIGSEGV)
Exception Codes:       KERN_INVALID_ADDRESS at 0x0000000000000000
Exception Note:        EXC_CORPSE_NOTIFY

Termination Signal:    Segmentation fault: 11
Termination Reason:    Namespace SIGNAL, Code 0xb
Terminating Process:   exc handler [0]

VM Regions Near 0:
--> 
    __TEXT                 000000010655f000-00000001065c1000 [  392K] r-x/rwx SM=COW  /Users/USER/*

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   libsystem_platform.dylib      	0x00007fffd0b22efc _platform_memmove$VARIANT$Haswell + 92
1   libcrypto.1.1.dylib           	0x00000001067aec0c RSA_padding_check_PKCS1_OAEP_mgf1 + 1612
2   libcrypto.1.1.dylib           	0x00000001067b131b pkey_rsa_decrypt + 171
3   pkcs11.dylib                  	0x000000010690293d pkcs11_pkey_rsa_decrypt + 1053
4   openssl                       	0x0000000106581391 pkeyutl_main + 3073
5   openssl                       	0x000000010657a1c6 do_cmd + 134
6   openssl                       	0x000000010657a132 main + 1186
7   libdyld.dylib                 	0x00007fffd0910235 start + 1

注意, 对于加密操作, libp11 可能会做的唯一一件事是获取公钥并将其传递给 OpenSSL。并且我验证了它仍然适用于 rsa-PSS (签名) 的原始-rsa 的标记。因此, 我打破了一些相关的加密, 不知何故..。

这是有问题的代码分支: https://github.com/mouse07410/libp11/commits/rsa-oaep-prep

原文:

Preliminary results

RSA-OAEP code works with the HSM device, but broke RSA-OAEP for Yubikey NEO (token that does raw RSA only). Interestingly, the crash occurs in the OpenSSL itself, and not only on the decryption attempts, but also on the attempt to encrypt.

$  ~/openssl-1.1/bin/openssl pkeyutl -engine pkcs11 -keyform engine -encrypt -pubin -inkey "pkcs11:token=Uri%20the%20Great;id=%03;type=public" -in t256.txt -out t256.txt.oaep3 -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha512 
engine "pkcs11" set.
Segmentation fault: 11
$ openssl pkeyutl -engine pkcs11 -keyform engine -encrypt -pubin -inkey "pkcs11:token=Uri%20the%20Great;id=%03;type=public" -in t256.txt -out t256.txt.oaep3 -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha512
engine "pkcs11" set.
$ openssl pkeyutl -engine pkcs11 -keyform engine -decrypt -inkey "pkcs11:token=Uri%20the%20Great;id=%03;type=private" -in t256.txt.oaep3 -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha512
engine "pkcs11" set.
Enter PKCS#11 token PIN for Uri the Great:
12345678901234567890123456789012     # good output
$ ~/openssl-1.1/bin/openssl pkeyutl -engine pkcs11 -keyform engine -decrypt -inkey "pkcs11:token=Uri%20the%20Great;id=%03;type=private" -in t256.txt.oaep3 -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha512
engine "pkcs11" set.
Enter PKCS#11 token PIN for Uri the Great:
RSA_OAEP
hashAlg=SHA384 mgf=MGF1-SHA512 
Segmentation fault: 11
$

Here's the encryption crash:

Exception Type:        EXC_BAD_ACCESS (SIGSEGV)
Exception Codes:       KERN_INVALID_ADDRESS at 0x0000000000000000
Exception Note:        EXC_CORPSE_NOTIFY

Termination Signal:    Segmentation fault: 11
Termination Reason:    Namespace SIGNAL, Code 0xb
Terminating Process:   exc handler [0]

VM Regions Near 0:
--> 
    __TEXT                 000000010f20b000-000000010f26d000 [  392K] r-x/rwx SM=COW  /Users/USER/*

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   libcrypto.1.1.dylib           	0x000000010f3555c8 BN_bn2bin + 136
1   libcrypto.1.1.dylib           	0x000000010f45cfb2 rsa_ossl_public_encrypt + 866
2   libcrypto.1.1.dylib           	0x000000010f45f23d pkey_rsa_encrypt + 205
3   openssl                       	0x000000010f22d37d pkeyutl_main + 3053
4   openssl                       	0x000000010f2261c6 do_cmd + 134
5   openssl                       	0x000000010f226132 main + 1186
6   libdyld.dylib                 	0x00007fffd0910235 start + 1

Here's the decryption crash:

Exception Type:        EXC_BAD_ACCESS (SIGSEGV)
Exception Codes:       KERN_INVALID_ADDRESS at 0x0000000000000000
Exception Note:        EXC_CORPSE_NOTIFY

Termination Signal:    Segmentation fault: 11
Termination Reason:    Namespace SIGNAL, Code 0xb
Terminating Process:   exc handler [0]

VM Regions Near 0:
--> 
    __TEXT                 000000010655f000-00000001065c1000 [  392K] r-x/rwx SM=COW  /Users/USER/*

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   libsystem_platform.dylib      	0x00007fffd0b22efc _platform_memmove$VARIANT$Haswell + 92
1   libcrypto.1.1.dylib           	0x00000001067aec0c RSA_padding_check_PKCS1_OAEP_mgf1 + 1612
2   libcrypto.1.1.dylib           	0x00000001067b131b pkey_rsa_decrypt + 171
3   pkcs11.dylib                  	0x000000010690293d pkcs11_pkey_rsa_decrypt + 1053
4   openssl                       	0x0000000106581391 pkeyutl_main + 3073
5   openssl                       	0x000000010657a1c6 do_cmd + 134
6   openssl                       	0x000000010657a132 main + 1186
7   libdyld.dylib                 	0x00007fffd0910235 start + 1

Note, that for encryption operation the only thing libp11 presumably does is fetching the public key and passing it to OpenSSL. And I verified that it still works for RSA-PSS (signing) with the raw-RSA-only tokens. So I broke something related to encryption, somehow...

This is the code branch in question: https://github.com/mouse07410/libp11/commits/rsa-oaep-prep

dengert 2017-10-9
60

再次我将要求您学习如何编译和链接调试符号并使用调试器。

原文:

Again I will ask you to learn how to compile and link with debugging symbols and use a debugger.

mouse07410 2017-10-9
61

我将要求您学习如何编译和链接调试符号并使用调试器。

在 Mac 上, 这并不容易。:-(
如何编译 OpenSSL 与调试-aka 如何我传递 "-g" 到配置?
它看起来像 ./config --debug . . . 的把戏 (不奇怪:()。

这是我的 OpenSSL 配置 + 生成脚本:

#!/bin/bash -ex

make distclean || true
# For OpenSSL-1.1.0-stable
./config --prefix=$HOME/openssl-1.1 --openssldir=$HOME/openssl-1.1/etc enable-ec_nistp_64_gcc_128 enable-md2 enable-rc5 enable-weak-ssl-ciphers enable-zlib-dynamic enable-tls1_3 enable-tls13downgrade
make depend && make clean && make -j 2 all && make test && make install
原文:

I will ask you to learn how to compile and link with debugging symbols and use a debugger.

On Mac it's not that easy. :-(
How do I compile OpenSSL with debugging - aka how to I pass "-g" to the Configure ?
It looks like ./config --debug . . . does the trick (unsurprisingly :().

This is my OpenSSL config+build script:

#!/bin/bash -ex

make distclean || true
# For OpenSSL-1.1.0-stable
./config --prefix=$HOME/openssl-1.1 --openssldir=$HOME/openssl-1.1/etc enable-ec_nistp_64_gcc_128 enable-md2 enable-rc5 enable-weak-ssl-ciphers enable-zlib-dynamic enable-tls1_3 enable-tls13downgrade
make depend && make clean && make -j 2 all && make test && make install
dengert 2017-10-9
62

添加-g 到配置参数。

https://wiki.openssl.org/index.php/Compilation_and_Installation#Configure_Options

-anythingelse, + anythingelse |编译器选项, 将成为 CFLAGS 的一部分。
可能还需要
导出 LDFLAGS =-g

原文:

Add -g to the Configure parameters.

https://wiki.openssl.org/index.php/Compilation_and_Installation#Configure_Options

-anythingelse, +anythingelse | Compiler options, will become part of CFLAGS.
May also need
export LDFLAGS=-g

mouse07410 2017-10-9
63

我对调试器从来没有太多的运气:

$ lldb apps/openssl
(lldb) target create "apps/openssl"
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/copy.py", line 52, in <module>
    import weakref
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/weakref.py", line 14, in <module>
    from _weakref import (
ImportError: cannot import name _remove_dead_weakref
Current executable set to 'apps/openssl' (x86_64).
(lldb) run pkeyutl -engine pkcs11 -keyform engine -encrypt -pubin -inkey "pkcs11:token=Uri%20the%20Great;id=%03;type=public" -in t256.txt -out t256.txt.oaep3 -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha512
error: shell expansion failed (reason: lldb-argdumper exited with error 127). consider launching with 'process launch'.
(lldb) process lunch apps/openssl pkeyutl -engine pkcs11 -keyform engine -encrypt -pubin -inkey "pkcs11:token=Uri%20the%20Great;id=%03;type=public" -in t256.txt -out t256.txt.oaep3 -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha512
invalid command 'process lunch'.
(lldb) lunch apps/openssl pkeyutl -engine pkcs11 -keyform engine -encrypt -pubin -inkey "pkcs11:token=Uri%20the%20Great;id=%03;type=public" -in t256.txt -out t256.txt.oaep3 -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha512
error: 'lunch' is not a valid command.
error: Unrecognized command 'lunch'.
(lldb) ^D
$ ggdb apps/openssl
GNU gdb (GDB) 7.12.1
Copyright (C) 2017 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-apple-darwin16.7.0".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from apps/openssl...done.
(gdb) run pkeyutl -engine pkcs11 -keyform engine -encrypt -pubin -inkey "pkcs11:token=Uri%20the%20Great;id=%03;type=public" -in t256.txt -out t256.txt.oaep3 -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha512
Starting program: /Users/uri/src/openssl/apps/openssl pkeyutl -engine pkcs11 -keyform engine -encrypt -pubin -inkey "pkcs11:token=Uri%20the%20Great;id=%03;type=public" -in t256.txt -out t256.txt.oaep3 -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha512
During startup program terminated with signal ?, Unknown signal.
(gdb) 
^D
$ lldb
(lldb) process launch -A true -X true 'apps/openssl pkeyutl -engine pkcs11 -keyform engine -encrypt -pubin -inkey "pkcs11:
Process 84129 launched: '/Users/uri/src/openssl/apps/openssl' (x86_64)
Invalid command 'apps/openssl pkeyutl -engine pkcs11 -keyform engine -encrypt -pubin -inkey "pkcs11:token=Uri%20the%20Great'; type "help" for a list.
Process 84129 exited with status = 1 (0x00000001) 
(lldb) 

但至少与调试符号, 我得到更多的信息:

Crashed Thread:        0  Dispatch queue: com.apple.main-thread

Exception Type:        EXC_BAD_ACCESS (SIGSEGV)
Exception Codes:       KERN_INVALID_ADDRESS at 0x0000000000000000
Exception Note:        EXC_CORPSE_NOTIFY

Termination Signal:    Segmentation fault: 11
Termination Reason:    Namespace SIGNAL, Code 0xb
Terminating Process:   exc handler [0]

VM Regions Near 0:
--> 
    __TEXT                 0000000101f58000-0000000101fd2000 [  488K] r-x/rwx SM=COW  /Users/USER/*

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   libcrypto.1.1.dylib           	0x000000010212e57b bn2binpad + 283 (bn_lib.c:545)
1   libcrypto.1.1.dylib           	0x000000010212e5c2 BN_bn2bin + 34 (bn_lib.c:559)
2   libcrypto.1.1.dylib           	0x00000001022679ab rsa_ossl_public_encrypt + 987 (rsa_ossl.c:144)
3   libcrypto.1.1.dylib           	0x0000000102264317 RSA_public_encrypt + 71 (rsa_crpt.c:31)
4   libcrypto.1.1.dylib           	0x000000010226aa81 pkey_rsa_encrypt + 289 (rsa_pmeth.c:308)
5   libcrypto.1.1.dylib           	0x0000000102210a70 EVP_PKEY_encrypt + 416 (pmeth_fn.c:167)
6   openssl                       	0x0000000101f87be0 do_keyop + 240 (pkeyutl.c:476)
7   openssl                       	0x0000000101f8738f pkeyutl_main + 2431 (pkeyutl.c:300)
8   openssl                       	0x0000000101f7d2f9 do_cmd + 233 (openssl.c:473)
9   openssl                       	0x0000000101f7cdb0 main + 624 (openssl.c:181)
10  libdyld.dylib                 	0x00007fffd0910235 start + 1

间谍显示正确的处理-它提供了正确的公钥 (模数和公共指数)。

原文:

Well, I never had much luck with debuggers:

$ lldb apps/openssl
(lldb) target create "apps/openssl"
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/copy.py", line 52, in <module>
    import weakref
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/weakref.py", line 14, in <module>
    from _weakref import (
ImportError: cannot import name _remove_dead_weakref
Current executable set to 'apps/openssl' (x86_64).
(lldb) run pkeyutl -engine pkcs11 -keyform engine -encrypt -pubin -inkey "pkcs11:token=Uri%20the%20Great;id=%03;type=public" -in t256.txt -out t256.txt.oaep3 -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha512
error: shell expansion failed (reason: lldb-argdumper exited with error 127). consider launching with 'process launch'.
(lldb) process lunch apps/openssl pkeyutl -engine pkcs11 -keyform engine -encrypt -pubin -inkey "pkcs11:token=Uri%20the%20Great;id=%03;type=public" -in t256.txt -out t256.txt.oaep3 -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha512
invalid command 'process lunch'.
(lldb) lunch apps/openssl pkeyutl -engine pkcs11 -keyform engine -encrypt -pubin -inkey "pkcs11:token=Uri%20the%20Great;id=%03;type=public" -in t256.txt -out t256.txt.oaep3 -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha512
error: 'lunch' is not a valid command.
error: Unrecognized command 'lunch'.
(lldb) ^D
$ ggdb apps/openssl
GNU gdb (GDB) 7.12.1
Copyright (C) 2017 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-apple-darwin16.7.0".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from apps/openssl...done.
(gdb) run pkeyutl -engine pkcs11 -keyform engine -encrypt -pubin -inkey "pkcs11:token=Uri%20the%20Great;id=%03;type=public" -in t256.txt -out t256.txt.oaep3 -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha512
Starting program: /Users/uri/src/openssl/apps/openssl pkeyutl -engine pkcs11 -keyform engine -encrypt -pubin -inkey "pkcs11:token=Uri%20the%20Great;id=%03;type=public" -in t256.txt -out t256.txt.oaep3 -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha512
During startup program terminated with signal ?, Unknown signal.
(gdb) 
^D
$ lldb
(lldb) process launch -A true -X true 'apps/openssl pkeyutl -engine pkcs11 -keyform engine -encrypt -pubin -inkey "pkcs11:
Process 84129 launched: '/Users/uri/src/openssl/apps/openssl' (x86_64)
Invalid command 'apps/openssl pkeyutl -engine pkcs11 -keyform engine -encrypt -pubin -inkey "pkcs11:token=Uri%20the%20Great'; type "help" for a list.
Process 84129 exited with status = 1 (0x00000001) 
(lldb) 

But at least with debugging symbols I'm getting more info:

Crashed Thread:        0  Dispatch queue: com.apple.main-thread

Exception Type:        EXC_BAD_ACCESS (SIGSEGV)
Exception Codes:       KERN_INVALID_ADDRESS at 0x0000000000000000
Exception Note:        EXC_CORPSE_NOTIFY

Termination Signal:    Segmentation fault: 11
Termination Reason:    Namespace SIGNAL, Code 0xb
Terminating Process:   exc handler [0]

VM Regions Near 0:
--> 
    __TEXT                 0000000101f58000-0000000101fd2000 [  488K] r-x/rwx SM=COW  /Users/USER/*

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   libcrypto.1.1.dylib           	0x000000010212e57b bn2binpad + 283 (bn_lib.c:545)
1   libcrypto.1.1.dylib           	0x000000010212e5c2 BN_bn2bin + 34 (bn_lib.c:559)
2   libcrypto.1.1.dylib           	0x00000001022679ab rsa_ossl_public_encrypt + 987 (rsa_ossl.c:144)
3   libcrypto.1.1.dylib           	0x0000000102264317 RSA_public_encrypt + 71 (rsa_crpt.c:31)
4   libcrypto.1.1.dylib           	0x000000010226aa81 pkey_rsa_encrypt + 289 (rsa_pmeth.c:308)
5   libcrypto.1.1.dylib           	0x0000000102210a70 EVP_PKEY_encrypt + 416 (pmeth_fn.c:167)
6   openssl                       	0x0000000101f87be0 do_keyop + 240 (pkeyutl.c:476)
7   openssl                       	0x0000000101f8738f pkeyutl_main + 2431 (pkeyutl.c:300)
8   openssl                       	0x0000000101f7d2f9 do_cmd + 233 (openssl.c:473)
9   openssl                       	0x0000000101f7cdb0 main + 624 (openssl.c:181)
10  libdyld.dylib                 	0x00007fffd0910235 start + 1

SPY showed correct processing - it provided the right public key (MODULUS and PUBLIC EXPONENT).

dengert 2017-10-9
64

我从没用过 lldblinux gdb 的作品。它看起来像 MaxOS 有 ggdb 和输出承诺。崩溃报告现在显示文件名和行号。

在你的第一个垃圾场, 它是在 pkcs11_pkey_rsa_decrypt 和 pkey_rsa_decrypt。这将表明, 在传递给 pkey_rsa_decrypt 的参数中可能存在问题。

但在第二次崩溃, 它是 pkey_rsa_encrypt, 这将表明它试图做一个加密将是与公钥。 你试图拍摄2单独的问题。一个是你的模式, 另一个不清楚, 如果你的 mods 在使用公钥的方式。

它看起来还没有安装新命令, 但正在尝试从生成目录中运行。这可能是一个错误的库被使用的问题。

gdb 有--参数选项。这使得在 gdb 命令行上放置参数变得很容易, 所以如果您试图运行:

 apps/openssl pkeyutl -engine pkcs11 -keyform engine -decrypt -inkey "pkcs11:token=Uri%20the%20Great;id=%03;type=private" -in t256.txt.oaep3 -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha512

只需继续执行命令ggdb --args
它甚至可以在一个脚本

ggdb --args apps/openssl pkeyutl -engine pkcs11 -keyform engine -decrypt -inkey "pkcs11:token=Uri%20the%20Great;id=%03;type=private" -in t256.txt.oaep3 -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha512

当您获得第一个 (gdb) 提示时, 请尝试输入以下内容:

break pkcs11_pkey_rsa_decrypt
break pkey_rsa_decrypt
run

当它停在pkcs11_pkey_rsa_decrypt
尝试逐句通过代码使用n
您可以使用 p 命令来查看变量和 structuctures
如果它是一个指针, 你可以做一些类似的事情:
p * variable它会显示你的结构。
bt也很有帮助。

可以使用 run 命令重新开始。

原文:

I never used lldb. On linux gdb works. It looks like MaxOS has ggdb and the output promising. The crash report now shows file names and line numbers.

In your first crash dump, it was in pkcs11_pkey_rsa_decrypt and pkey_rsa_decrypt. That would indicate that there may be a problem in the arguments passed to pkey_rsa_decrypt.

But in the second crash it is pkey_rsa_encrypt which would indicate it is trying to do an encrypt would would be with the public key. You are trying to shoot 2 separate problems. One is your modes, and the other is not clear if your mods get in the way when using the public key.

It also looks like you have not installed the new commands, but are trying to run out of the build directory. That could be an issue with the wrong libs being used.

gdb has the --args option. This make it easy to put the arguments on the gdb command line so if you are trying to run:

 apps/openssl pkeyutl -engine pkcs11 -keyform engine -decrypt -inkey "pkcs11:token=Uri%20the%20Great;id=%03;type=private" -in t256.txt.oaep3 -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha512

just proceed the command with ggdb --args
It could even be in a script

ggdb --args apps/openssl pkeyutl -engine pkcs11 -keyform engine -decrypt -inkey "pkcs11:token=Uri%20the%20Great;id=%03;type=private" -in t256.txt.oaep3 -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha512

When you get the first (gdb) prompt try entering these:

break pkcs11_pkey_rsa_decrypt
break pkey_rsa_decrypt
run

Then when it stops at pkcs11_pkey_rsa_decrypt
try stepping through the code using n
You can look at variables and structuctures using the p command
If its a pointer you can do something like:
p * variable and it will show you the structure.
bt is also helpful.

You can start over using the run command.

mouse07410 2017-10-9
65

首先 all-thank 你!!

仍然没有太多的运气与 ggdb (确实在 Linux 上, 它的行为更好):

ggdb --args  ~/openssl-1.1/bin/openssl pkeyutl -engine pkcs11 -keyform engine -decrypt -inkey "pkcs11:token=Uri%20the%20Great;id=%03;type=private" -in t256.txt.oaep2 -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha512
GNU gdb (GDB) 7.12.1
Copyright (C) 2017 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-apple-darwin16.7.0".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from /Users/uri/openssl-1.1/bin/openssl...done.
(gdb) break pkcs11_pkey_rsa_decrypt
Function "pkcs11_pkey_rsa_decrypt" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (pkcs11_pkey_rsa_decrypt) pending.
(gdb) break pkey_rsa_decrypt
Function "pkey_rsa_decrypt" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 2 (pkey_rsa_decrypt) pending.
(gdb) run
Starting program: /Users/uri/openssl-1.1/bin/openssl pkeyutl -engine pkcs11 -keyform engine -decrypt -inkey pkcs11:token=Uri%20the%20Great\;id=%03\;type=private -in t256.txt.oaep2 -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha512
During startup program terminated with signal ?, Unknown signal.
(gdb) 

但有些更好的运气与直接踪影:

在您的帮助下, RSA-OAEP 解密似乎是固定的。

$ ~/openssl-1.1/bin/openssl pkeyutl -engine pkcs11 -keyform engine -decrypt -inkey "pkcs11:token=Uri%20the%20Great;object=KEY%20MAN%20key;type=private" -in t256.txt.oaep2 -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha512
engine "pkcs11" set.
Enter PKCS#11 token PIN for Uri the Great:
Entered pkcs11_pkey_rsa_decrypt() out=0x0  *outlen=1833709100 in=0x7fc7a26063d0 inlen=256
RSA_OAEP
hashAlg=SHA384 mgf=MGF1-SHA512 
Entered pkcs11_pkey_rsa_decrypt() out=0x117b6b000  *outlen=1833709100 in=0x7fc7a26063d0 inlen=256
RSA_OAEP
hashAlg=SHA384 mgf=MGF1-SHA512 
12345678901234567890123456789012
$ 

加密 (即, 仅公钥操作) 仍然被破坏。工作。

原文:

First of all - thank you!!

Still not much luck with ggdb (indeed on Linux it behaves better):

ggdb --args  ~/openssl-1.1/bin/openssl pkeyutl -engine pkcs11 -keyform engine -decrypt -inkey "pkcs11:token=Uri%20the%20Great;id=%03;type=private" -in t256.txt.oaep2 -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha512
GNU gdb (GDB) 7.12.1
Copyright (C) 2017 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-apple-darwin16.7.0".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from /Users/uri/openssl-1.1/bin/openssl...done.
(gdb) break pkcs11_pkey_rsa_decrypt
Function "pkcs11_pkey_rsa_decrypt" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (pkcs11_pkey_rsa_decrypt) pending.
(gdb) break pkey_rsa_decrypt
Function "pkey_rsa_decrypt" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 2 (pkey_rsa_decrypt) pending.
(gdb) run
Starting program: /Users/uri/openssl-1.1/bin/openssl pkeyutl -engine pkcs11 -keyform engine -decrypt -inkey pkcs11:token=Uri%20the%20Great\;id=%03\;type=private -in t256.txt.oaep2 -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha512
During startup program terminated with signal ?, Unknown signal.
(gdb) 

But somewhat better luck with direct traces:

With your help, RSA-OAEP decryption seems fixed.

$ ~/openssl-1.1/bin/openssl pkeyutl -engine pkcs11 -keyform engine -decrypt -inkey "pkcs11:token=Uri%20the%20Great;object=KEY%20MAN%20key;type=private" -in t256.txt.oaep2 -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha512
engine "pkcs11" set.
Enter PKCS#11 token PIN for Uri the Great:
Entered pkcs11_pkey_rsa_decrypt() out=0x0  *outlen=1833709100 in=0x7fc7a26063d0 inlen=256
RSA_OAEP
hashAlg=SHA384 mgf=MGF1-SHA512 
Entered pkcs11_pkey_rsa_decrypt() out=0x117b6b000  *outlen=1833709100 in=0x7fc7a26063d0 inlen=256
RSA_OAEP
hashAlg=SHA384 mgf=MGF1-SHA512 
12345678901234567890123456789012
$ 

Encryption (i.e., public key only operation) is still broken. Working on it.

mouse07410 2017-10-9
66

我观察到的是, 对于解密, pkey_rsa_decrypt() 被输入了两次--一次用于确定输出缓冲区大小, 第二个 (实际解密。

看起来类似的事情也在这里发生, 虽然我不知道为什么。下面是由引擎提供的公钥的失败跟踪-注意 pkey_rsa_encrypt() 输入时带有输出缓冲区 out=0x0 (请求将密码文本存储到空 PTR 中):

$ ~/openssl-1.1/bin/openssl pkeyutl -engine pkcs11 -keyform engine -encrypt -pubin -inkey "pkcs11:token=Uri%20the%20Great;id=%03;type=public" -in t256.txt -out t256.txt.oaep3 -pkeyopt rsa_padding_mode:oaep
engine "pkcs11" set.
pkey_rsa_encrypt(): out=0x0 outlen=140734771107648 in=0x7ff9e8639930 inlen=33
...RSA_PKCS1_PAEP_PADDING tbuf=0x7ff9e8639ee0 klen=256 md=SHA1 mgf1md=SHA1
...before RSA_public_encypt klen=256 tbuf=0x7ff9e8639ee0 out=0x0 rsa=0x7ff9e8607560
Segmentation fault: 11
$

相同的操作在同一项上, 但从标记中提取并存储在一个文件中 (即 pkcs11 引擎根本不涉及):

$ ~/openssl-1.1/bin/openssl pkeyutl -keyform DER -encrypt -pubin -inkey rsa2048pub.der -in t256.txt -out t256.txt.oaep3 -pkeyopt rsa_padding_mode:oaep
pkey_rsa_encrypt(): out=0x7fe2f1c150f0 outlen=140734648977280 in=0x7fe2f1c14cc0 inlen=33
...RSA_PKCS1_PAEP_PADDING tbuf=0x7fe2f1c151f0 klen=256 md=SHA1 mgf1md=SHA1
...before RSA_public_encypt klen=256 tbuf=0x7fe2f1c151f0 out=0x7fe2f1c150f0 rsa=0x7fe2f1c14e50
...RSA_public_encrypt() returned 256
$

下面是在令牌上的酒吧钥匙的情况下的崩溃报告:

Exception Type:        EXC_BAD_ACCESS (SIGSEGV)
Exception Codes:       KERN_INVALID_ADDRESS at 0x0000000000000000
Exception Note:        EXC_CORPSE_NOTIFY

Termination Signal:    Segmentation fault: 11
Termination Reason:    Namespace SIGNAL, Code 0xb
Terminating Process:   exc handler [0]

VM Regions Near 0:
--> 
    __TEXT                 0000000101b5d000-0000000101bd7000 [  488K] r-x/rwx SM=COW  /Users/USER/*

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   libcrypto.1.1.dylib           	0x0000000101d3157b bn2binpad + 283 (bn_lib.c:545)
1   libcrypto.1.1.dylib           	0x0000000101d315c2 BN_bn2bin + 34 (bn_lib.c:559)
2   libcrypto.1.1.dylib           	0x0000000101e6a9ab rsa_ossl_public_encrypt + 987 (rsa_ossl.c:144)
3   libcrypto.1.1.dylib           	0x0000000101e67317 RSA_public_encrypt + 71 (rsa_crpt.c:31)
4   libcrypto.1.1.dylib           	0x0000000101e6db33 pkey_rsa_encrypt + 467 (rsa_pmeth.c:315)
5   libcrypto.1.1.dylib           	0x0000000101e13a70 EVP_PKEY_encrypt + 416 (pmeth_fn.c:167)
6   openssl                       	0x0000000101b8cbe0 do_keyop + 240 (pkeyutl.c:476)
7   openssl                       	0x0000000101b8c38f pkeyutl_main + 2431 (pkeyutl.c:300)
8   openssl                       	0x0000000101b822f9 do_cmd + 233 (openssl.c:473)
9   openssl                       	0x0000000101b81db0 main + 624 (openssl.c:181)
10  libdyld.dylib                 	0x00007fffd0910235 start + 1
原文:

What I observed was that for decryption, the pkey_rsa_decrypt() was entered twice - once to determine the output buffer size, and the second time - for the real decryption.

It looks like something similar is happening here as well, although I can't figure why. Here's the failing trace when the public key is provided by the engine - notice that pkey_rsa_encrypt() is entered with the output buffer out=0x0 (requesting to store the cipher text into a NULL PTR):

$ ~/openssl-1.1/bin/openssl pkeyutl -engine pkcs11 -keyform engine -encrypt -pubin -inkey "pkcs11:token=Uri%20the%20Great;id=%03;type=public" -in t256.txt -out t256.txt.oaep3 -pkeyopt rsa_padding_mode:oaep
engine "pkcs11" set.
pkey_rsa_encrypt(): out=0x0 outlen=140734771107648 in=0x7ff9e8639930 inlen=33
...RSA_PKCS1_PAEP_PADDING tbuf=0x7ff9e8639ee0 klen=256 md=SHA1 mgf1md=SHA1
...before RSA_public_encypt klen=256 tbuf=0x7ff9e8639ee0 out=0x0 rsa=0x7ff9e8607560
Segmentation fault: 11
$

Same operation on the same key, but extracted from the token and stored in a file (i.e., pkcs11 engine is not involved at all):

$ ~/openssl-1.1/bin/openssl pkeyutl -keyform DER -encrypt -pubin -inkey rsa2048pub.der -in t256.txt -out t256.txt.oaep3 -pkeyopt rsa_padding_mode:oaep
pkey_rsa_encrypt(): out=0x7fe2f1c150f0 outlen=140734648977280 in=0x7fe2f1c14cc0 inlen=33
...RSA_PKCS1_PAEP_PADDING tbuf=0x7fe2f1c151f0 klen=256 md=SHA1 mgf1md=SHA1
...before RSA_public_encypt klen=256 tbuf=0x7fe2f1c151f0 out=0x7fe2f1c150f0 rsa=0x7fe2f1c14e50
...RSA_public_encrypt() returned 256
$

Here's the crash report for the case when pub key is on the token:

Exception Type:        EXC_BAD_ACCESS (SIGSEGV)
Exception Codes:       KERN_INVALID_ADDRESS at 0x0000000000000000
Exception Note:        EXC_CORPSE_NOTIFY

Termination Signal:    Segmentation fault: 11
Termination Reason:    Namespace SIGNAL, Code 0xb
Terminating Process:   exc handler [0]

VM Regions Near 0:
--> 
    __TEXT                 0000000101b5d000-0000000101bd7000 [  488K] r-x/rwx SM=COW  /Users/USER/*

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   libcrypto.1.1.dylib           	0x0000000101d3157b bn2binpad + 283 (bn_lib.c:545)
1   libcrypto.1.1.dylib           	0x0000000101d315c2 BN_bn2bin + 34 (bn_lib.c:559)
2   libcrypto.1.1.dylib           	0x0000000101e6a9ab rsa_ossl_public_encrypt + 987 (rsa_ossl.c:144)
3   libcrypto.1.1.dylib           	0x0000000101e67317 RSA_public_encrypt + 71 (rsa_crpt.c:31)
4   libcrypto.1.1.dylib           	0x0000000101e6db33 pkey_rsa_encrypt + 467 (rsa_pmeth.c:315)
5   libcrypto.1.1.dylib           	0x0000000101e13a70 EVP_PKEY_encrypt + 416 (pmeth_fn.c:167)
6   openssl                       	0x0000000101b8cbe0 do_keyop + 240 (pkeyutl.c:476)
7   openssl                       	0x0000000101b8c38f pkeyutl_main + 2431 (pkeyutl.c:300)
8   openssl                       	0x0000000101b822f9 do_cmd + 233 (openssl.c:473)
9   openssl                       	0x0000000101b81db0 main + 624 (openssl.c:181)
10  libdyld.dylib                 	0x00007fffd0910235 start + 1
dengert 2017-10-9
67

请注意, 与引擎, 当 OpenSSL 寻找一个 ENV_PKEY_meth, 它会找到修改后的版本, 因为 evp_pkey 有一个引擎集。因此, 它会找到修改后的版本。但只有2例程序应该改变。你换了其他人吗? pkey_rsa_encrypt 不应该被替换。

与文件一起使用时, 它会找到默认的 pkey_rsa_encrypt。

明白了

pkey_rsa_encrypt(): out=0x0 outlen=140734771107648 in=0x7ff9e8639930 inlen=33
...RSA_PKCS1_PAEP_PADDING tbuf=0x7ff9e8639ee0 klen=256 md=SHA1 mgf1md=SHA1
...before RSA_public_encypt klen=256 tbuf=0x7ff9e8639ee0 out=0x0 rsa=0x7ff9e8607560

在您的输出中。 您添加的是一些调试信息吗?

原文:

Note that with the engine, when OpenSSL looks for a ENV_PKEY_meth, it will find the modified version because the evp_pkey has an engine set. So it will find the modified version. But only 2 routines should have been change. Did you change any others? pkey_rsa_encrypt should not have been replaced.

When used with the file it will find the default pkey_rsa_encrypt.

I see

pkey_rsa_encrypt(): out=0x0 outlen=140734771107648 in=0x7ff9e8639930 inlen=33
...RSA_PKCS1_PAEP_PADDING tbuf=0x7ff9e8639ee0 klen=256 md=SHA1 mgf1md=SHA1
...before RSA_public_encypt klen=256 tbuf=0x7ff9e8639ee0 out=0x0 rsa=0x7ff9e8607560

in your output. Is that some debugging info you added?

mouse07410 2017-10-9
68

请注意, 在引擎中, 当 OpenSSL 查找 EVP_PKEY_meth 时, 它会找到修改后的版本, 因为 evp_pkey 有一个引擎集。因此, 它会找到修改后的版本。

明白了。此 EVP_PKEY_meth 包括所有内容, 对吗?签名, 验证, 加密, 解密?

你换了其他人吗?

否!我当然没有我不是在找麻烦, 即使它看起来像我.;-)
此外, 您还可以在https://github.com/mouse07410/libp11/tree/rsa-oaep-prep中看到当前代码

...您添加的是一些调试信息吗?

哦,是的。由于无法通过调试器查看事物, 因此不得不求助于旧方法。;-)

pkey_rsa_encrypt 不应该被替换。

但它看起来不像 pkey_rsa_encrypt()替换的-它看起来像是与引擎出于某种原因 pkey_rsa_encrypt() 每个加密操作都称为两次: 一次使用 out=NULL 来了解密文的大小和第二次实际上提供了接收密文的 out 缓冲区。我验证: 没有引擎 (当公钥在磁盘文件中) pkey_rsa_encrypt() 只调用一次!

我对这种行为没有任何解释。此外, 原始主控形状似乎没有触发此行为。

我当前解决此问题的方法是将以下内容添加到 openssl/crypto/rsa/rsa_pmeth.c ...encrypt() 调用之前的文件 RSA_public_encrypt() :

        if (out == NULL) {
                *outlen = klen;
                return 1;
        }
        ret = RSA_public_encrypt(klen, rctx->tbuf, out,
                                 ctx->pkey->pkey.rsa, RSA_NO_PADDING);

它纠正了这种情况。

我看到两个选项 (它们不是互斥的):

试图说服 OpenSSL 团队为 out==NULL 添加检查, 如果是, 则设置密码文本所需缓冲区的长度并返回 OK。
b. 在 libp11 替换 pkey_rsa_encrypt() 中, pkcs11_pkey_rsa_encrypt() ,主要从 OpenSSL rsa_pmeth.c 中的该函数中窃取代码, 以确保当给定的输出缓冲区是空指针时它做正确的事情 (调用是只了解要分配的缓冲区的长度为密文)。

@dengert@mtrojnar你的意见是什么?你同意我的诊断吗?您是否同意可用的备选方案的列表 (是否有其他选择, 我错过了)?你有偏好吗?我想我倾向于 (b), 但它取决于@mtrojnar该选项是否可以飞行.

下面是截图 (文件 t256.txt 包含 ASCII 字符串 12345678901234567890123456789012 ):

$  ~/openssl-1.1/bin/openssl pkeyutl -engine pkcs11 -keyform engine -encrypt -pubin -inkey "pkcs11:token=YubiHSM;id=%03%02;type=public" -in t256.txt -out t256.txt.oaephsm -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha512
engine "pkcs11" set.
Enter PKCS#11 token PIN for YubiHSM:
pkey_rsa_encrypt(): out=0x0 outlen=140734581749488 in=0x7fee3bd47d90 inlen=33
...RSA_PKCS1_PAEP_PADDING tbuf=0x7fee3bd48460 klen=384 md=SHA384 mgf1md=SHA384
...before RSA_public_encypt klen=384 tbuf=0x7fee3bd48460 out=0x0 rsa=0x7fee3bc22dd0
pkey_rsa_encrypt(): out=0x7fee3be05a90 outlen=140734581749488 in=0x7fee3bd47d90 inlen=33
...RSA_PKCS1_PAEP_PADDING tbuf=0x7fee3bd48460 klen=384 md=SHA384 mgf1md=SHA384
...before RSA_public_encypt klen=384 tbuf=0x7fee3bd48460 out=0x7fee3be05a90 rsa=0x7fee3bc22dd0
...RSA_public_encrypt() returned 384
$  ~/openssl-1.1/bin/openssl pkeyutl -engine pkcs11 -keyform engine -decrypt -inkey "pkcs11:token=YubiHSM;id=%03%02;type=private" -in t256.txt.oaephsm -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha512
engine "pkcs11" set.
Enter PKCS#11 token PIN for YubiHSM:
Entered pkcs11_pkey_rsa_decrypt() out=0x0  *outlen=1833709100 in=0x7fe8b9f105b0 inlen=384
RSA_OAEP
hashAlg=SHA384 mgf=MGF1-SHA512 
Entered pkcs11_pkey_rsa_decrypt() out=0x7fe8b9d166a0  *outlen=33 in=0x7fe8b9f105b0 inlen=384
RSA_OAEP
hashAlg=SHA384 mgf=MGF1-SHA512 
12345678901234567890123456789012
$  ~/openssl-1.1/bin/openssl pkeyutl -engine pkcs11 -keyform engine -encrypt -pubin -inkey "pkcs11:token=Uri%20the%20Great;id=%03;type=public" -in t256.txt -out t256.txt.oaepneo -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha512
engine "pkcs11" set.
pkey_rsa_encrypt(): out=0x0 outlen=140734685615840 in=0x7f8b34f0b9b0 inlen=33
...RSA_PKCS1_PAEP_PADDING tbuf=0x7f8b34f0bf60 klen=256 md=SHA384 mgf1md=SHA384
...before RSA_public_encypt klen=256 tbuf=0x7f8b34f0bf60 out=0x0 rsa=0x7f8b34f09250
pkey_rsa_encrypt(): out=0x7f8b34e116b0 outlen=140734685615840 in=0x7f8b34f0b9b0 inlen=33
...RSA_PKCS1_PAEP_PADDING tbuf=0x7f8b34f0bf60 klen=256 md=SHA384 mgf1md=SHA384
...before RSA_public_encypt klen=256 tbuf=0x7f8b34f0bf60 out=0x7f8b34e116b0 rsa=0x7f8b34f09250
...RSA_public_encrypt() returned 256
$  ~/openssl-1.1/bin/openssl pkeyutl -engine pkcs11 -keyform engine -decrypt -inkey "pkcs11:token=Uri%20the%20Great;id=%03;type=private" -in t256.txt.oaepneo -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha512
engine "pkcs11" set.
Enter PKCS#11 token PIN for Uri the Great:
Entered pkcs11_pkey_rsa_decrypt() out=0x0  *outlen=1833709100 in=0x7fa9fe554840 inlen=256
RSA_OAEP
hashAlg=SHA384 mgf=MGF1-SHA512 
Entered pkcs11_pkey_rsa_decrypt() out=0x10e975000  *outlen=1833709100 in=0x7fa9fe554840 inlen=256
RSA_OAEP
hashAlg=SHA384 mgf=MGF1-SHA512 
12345678901234567890123456789012
$ pkcs11-tool -r --id 03 --type pubkey -o rsa2048pub.der
Using slot 0 with a present token (0x0)
$ ~/openssl-1.1/bin/openssl pkeyutl -keyform DER -encrypt -pubin -inkey rsa2048pub.der -in t256.txt -out t256.txt.oaepneo2 -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha512
pkey_rsa_encrypt(): out=0x7f9ff8e01b50 outlen=140734635603760 in=0x7f9ff8e015a0 inlen=33
...RSA_PKCS1_PAEP_PADDING tbuf=0x7f9ff8e01c50 klen=256 md=SHA384 mgf1md=SHA384
...before RSA_public_encypt klen=256 tbuf=0x7f9ff8e01c50 out=0x7f9ff8e01b50 rsa=0x7f9ff8e00570
...RSA_public_encrypt() returned 256
$  ~/openssl-1.1/bin/openssl pkeyutl -engine pkcs11 -keyform engine -decrypt -inkey "pkcs11:token=Uri%20the%20Great;id=%03;type=private" -in t256.txt.oaepneo2 -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha512
engine "pkcs11" set.
Enter PKCS#11 token PIN for Uri the Great:
Entered pkcs11_pkey_rsa_decrypt() out=0x0  *outlen=1833709100 in=0x7fa48e70f210 inlen=256
RSA_OAEP
hashAlg=SHA384 mgf=MGF1-SHA512 
Entered pkcs11_pkey_rsa_decrypt() out=0x10ff0f000  *outlen=1833709100 in=0x7fa48e70f210 inlen=256
RSA_OAEP
hashAlg=SHA384 mgf=MGF1-SHA512 
12345678901234567890123456789012
$ 

更新
同时, 我实现了 pkcs11_pkey_rsa_encrypt() 。结果是如此简单以至于不值得等待 (并且它在 PIV 模式和 HSM 中用 Yubikey 的 NEO 进行了测试)。

更新2
我认为 OpenSSL-1.0.2 的问题是, 此代码使用的函数仅在 OpenSSL-1.1 中可用。 但我还没有找到该函数.:-(

更新3
所讨论的函数似乎是 src/eng_front.c 中所需的功能:

  • EVP_PKEY_meth_get_sign()
  • EVP_PKEY_meth_get_decrypt()
  • EVP_PKEY_meth_get_encrypt()

是否有办法得到他们的等值在 OpenSSL-1.0.2?

原文:

Note that with the engine, when OpenSSL looks for a EVP_PKEY_meth, it will find the modified version because the evp_pkey has an engine set. So it will find the modified version.

I see. And this EVP_PKEY_meth includes everything, right? Sign, verify, encrypt, decrypt?

Did you change any others?

No! I certainly did not. I'm not looking for trouble, even if it might look like I am. ;-)
Plus, you can see the current code at https://github.com/mouse07410/libp11/tree/rsa-oaep-prep

...Is that some debugging info you added?

Oh yes. Being unable to view things via debugger, have to resort to the old ways. ;-)

pkey_rsa_encrypt should not have been replaced.

But it does not look like pkey_rsa_encrypt() was replaced - what it does look like is that with the engine for some reason pkey_rsa_encrypt() is called twice per encrypt operation: once with out=NULL to learn the size of the ciphertext and the second time to actually provide the out buffer to receive the ciphertext. I verified: without the engine (when the public key is in a disk file) pkey_rsa_encrypt() is called only once!

I have no explanation for this behavior. Also, the original master does not seem to trigger this behavior.

My current workaround for this problem is adding the following to openssl/crypto/rsa/rsa_pmeth.c file right before the ...encrypt() is calling RSA_public_encrypt():

        if (out == NULL) {
                *outlen = klen;
                return 1;
        }
        ret = RSA_public_encrypt(klen, rctx->tbuf, out,
                                 ctx->pkey->pkey.rsa, RSA_NO_PADDING);

It remedies the situation.

I see two options (they are not mutually-exclusive):

a. Try to convince OpenSSL team to add the check for out==NULL, and if so, set the length of the required buffer for the cipher text and return OK.
b. In libp11 replace pkey_rsa_encrypt() with pkcs11_pkey_rsa_encrypt(), mostly stealing the code from that function in OpenSSL rsa_pmeth.c - to ensure that it does the right thing when the given output buffer is a null-pointer (the call is made to only learn the length of the buffer to allocate for ciphertext).

@dengert and @mtrojnar what is your opinion? Do you concur with my diagnosis? Do you agree with the list of the available alternatives (are there other options that I missed)? Do you have a preference? I think I'm leaning towards (b), but it's up to @mtrojnar whether that option can fly.

Here's the screenshot (file t256.txt contains ASCII string 12345678901234567890123456789012):

$  ~/openssl-1.1/bin/openssl pkeyutl -engine pkcs11 -keyform engine -encrypt -pubin -inkey "pkcs11:token=YubiHSM;id=%03%02;type=public" -in t256.txt -out t256.txt.oaephsm -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha512
engine "pkcs11" set.
Enter PKCS#11 token PIN for YubiHSM:
pkey_rsa_encrypt(): out=0x0 outlen=140734581749488 in=0x7fee3bd47d90 inlen=33
...RSA_PKCS1_PAEP_PADDING tbuf=0x7fee3bd48460 klen=384 md=SHA384 mgf1md=SHA384
...before RSA_public_encypt klen=384 tbuf=0x7fee3bd48460 out=0x0 rsa=0x7fee3bc22dd0
pkey_rsa_encrypt(): out=0x7fee3be05a90 outlen=140734581749488 in=0x7fee3bd47d90 inlen=33
...RSA_PKCS1_PAEP_PADDING tbuf=0x7fee3bd48460 klen=384 md=SHA384 mgf1md=SHA384
...before RSA_public_encypt klen=384 tbuf=0x7fee3bd48460 out=0x7fee3be05a90 rsa=0x7fee3bc22dd0
...RSA_public_encrypt() returned 384
$  ~/openssl-1.1/bin/openssl pkeyutl -engine pkcs11 -keyform engine -decrypt -inkey "pkcs11:token=YubiHSM;id=%03%02;type=private" -in t256.txt.oaephsm -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha512
engine "pkcs11" set.
Enter PKCS#11 token PIN for YubiHSM:
Entered pkcs11_pkey_rsa_decrypt() out=0x0  *outlen=1833709100 in=0x7fe8b9f105b0 inlen=384
RSA_OAEP
hashAlg=SHA384 mgf=MGF1-SHA512 
Entered pkcs11_pkey_rsa_decrypt() out=0x7fe8b9d166a0  *outlen=33 in=0x7fe8b9f105b0 inlen=384
RSA_OAEP
hashAlg=SHA384 mgf=MGF1-SHA512 
12345678901234567890123456789012
$  ~/openssl-1.1/bin/openssl pkeyutl -engine pkcs11 -keyform engine -encrypt -pubin -inkey "pkcs11:token=Uri%20the%20Great;id=%03;type=public" -in t256.txt -out t256.txt.oaepneo -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha512
engine "pkcs11" set.
pkey_rsa_encrypt(): out=0x0 outlen=140734685615840 in=0x7f8b34f0b9b0 inlen=33
...RSA_PKCS1_PAEP_PADDING tbuf=0x7f8b34f0bf60 klen=256 md=SHA384 mgf1md=SHA384
...before RSA_public_encypt klen=256 tbuf=0x7f8b34f0bf60 out=0x0 rsa=0x7f8b34f09250
pkey_rsa_encrypt(): out=0x7f8b34e116b0 outlen=140734685615840 in=0x7f8b34f0b9b0 inlen=33
...RSA_PKCS1_PAEP_PADDING tbuf=0x7f8b34f0bf60 klen=256 md=SHA384 mgf1md=SHA384
...before RSA_public_encypt klen=256 tbuf=0x7f8b34f0bf60 out=0x7f8b34e116b0 rsa=0x7f8b34f09250
...RSA_public_encrypt() returned 256
$  ~/openssl-1.1/bin/openssl pkeyutl -engine pkcs11 -keyform engine -decrypt -inkey "pkcs11:token=Uri%20the%20Great;id=%03;type=private" -in t256.txt.oaepneo -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha512
engine "pkcs11" set.
Enter PKCS#11 token PIN for Uri the Great:
Entered pkcs11_pkey_rsa_decrypt() out=0x0  *outlen=1833709100 in=0x7fa9fe554840 inlen=256
RSA_OAEP
hashAlg=SHA384 mgf=MGF1-SHA512 
Entered pkcs11_pkey_rsa_decrypt() out=0x10e975000  *outlen=1833709100 in=0x7fa9fe554840 inlen=256
RSA_OAEP
hashAlg=SHA384 mgf=MGF1-SHA512 
12345678901234567890123456789012
$ pkcs11-tool -r --id 03 --type pubkey -o rsa2048pub.der
Using slot 0 with a present token (0x0)
$ ~/openssl-1.1/bin/openssl pkeyutl -keyform DER -encrypt -pubin -inkey rsa2048pub.der -in t256.txt -out t256.txt.oaepneo2 -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha512
pkey_rsa_encrypt(): out=0x7f9ff8e01b50 outlen=140734635603760 in=0x7f9ff8e015a0 inlen=33
...RSA_PKCS1_PAEP_PADDING tbuf=0x7f9ff8e01c50 klen=256 md=SHA384 mgf1md=SHA384
...before RSA_public_encypt klen=256 tbuf=0x7f9ff8e01c50 out=0x7f9ff8e01b50 rsa=0x7f9ff8e00570
...RSA_public_encrypt() returned 256
$  ~/openssl-1.1/bin/openssl pkeyutl -engine pkcs11 -keyform engine -decrypt -inkey "pkcs11:token=Uri%20the%20Great;id=%03;type=private" -in t256.txt.oaepneo2 -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha512
engine "pkcs11" set.
Enter PKCS#11 token PIN for Uri the Great:
Entered pkcs11_pkey_rsa_decrypt() out=0x0  *outlen=1833709100 in=0x7fa48e70f210 inlen=256
RSA_OAEP
hashAlg=SHA384 mgf=MGF1-SHA512 
Entered pkcs11_pkey_rsa_decrypt() out=0x10ff0f000  *outlen=1833709100 in=0x7fa48e70f210 inlen=256
RSA_OAEP
hashAlg=SHA384 mgf=MGF1-SHA512 
12345678901234567890123456789012
$ 

Update
In the meanwhile I implemented pkcs11_pkey_rsa_encrypt(). It turned out so simple that it wasn't worth waiting (and it works - tested with Yubikey NEO in PIV mode, and HSM).

Update 2
I think the problem with OpenSSL-1.0.2 is that this code uses a function that is only available in OpenSSL-1.1. But I haven't located that function yet. :-(

Update 3
The functions in question appear to be those needed in src/eng_front.c:

  • EVP_PKEY_meth_get_sign()
  • EVP_PKEY_meth_get_decrypt()
  • EVP_PKEY_meth_get_encrypt()

Is there a way to get their equivalent in OpenSSL-1.0.2?

dengert 2017-10-9
69

我相信问题不在 OpenSSL, 所以不需要 OpenSSL mods。

"do_original" 概念是;如果我们不能在我们的日常工作中, 后退, 让 OpenSSL 尝试, 也许失败。不应修改任何参数。在 p11_rsa 的 pkcs11_pkey_rsa_decrypt:

  • 删除:
701                 rv = (*orig_pkey_rsa_decrypt)(evp_pkey_ctx, out_buf, &size, in, inlen);
702                 if (rv >= 0) {
703                         *outlen = size;
704                         return size;
705                 } else
706                         return rv;
707         } else
  • 删除或移动到 rv 检查后。它修改 * outlen 和 orig_pkey_rsa_decrypt 可能需要调用。
676         /* Make sure we aren't overstepping provided output buffer size */
677         if (out == NULL || *outlen == 0 || *outlen >= size)
678                 *outlen = size;
679         
  • 我看不出原来的 pkey_rsa_decrypt 如何工作, 如果出 = NULL。但我没有运行调试器, 看看是否是这样。

  • *outlensize_tsize 为 CK_ULONG。看起来代码可能只在字节的机器上工作。

  • 我不会尝试做任何其他的 rsa 填充, 目前的工作。坚持让 OAEP 工作。

原文:

I believe the problems are not in OpenSSL, so no OPenSSL mods should be needed.

The "do_original" concept is; if we can't do it in our routines, fall back and let OpenSSL try and maybe fail. No parameters should be modified. In p11_rsa.c in pkcs11_pkey_rsa_decrypt:

  • delete:
701                 rv = (*orig_pkey_rsa_decrypt)(evp_pkey_ctx, out_buf, &size, in, inlen);
702                 if (rv >= 0) {
703                         *outlen = size;
704                         return size;
705                 } else
706                         return rv;
707         } else
  • Delete or move till after the rv is checked. It modifies *outlen and the orig_pkey_rsa_decrypt may need to be called.
676         /* Make sure we aren't overstepping provided output buffer size */
677         if (out == NULL || *outlen == 0 || *outlen >= size)
678                 *outlen = size;
679         
  • I don't see how the original pkey_rsa_decrypt could work if out=NULL. But I have not run a debugger on it to see if that is the case.

  • *outlen is a size_t but size is CK_ULONG. It looks like the code may only work on little-endian machines.

  • I would not try and do any other rsa padding, that currently work. stick with getting OAEP working.

dengert 2017-10-9
70

你为什么要实施 pkcs11_evp_rsa_encrypt?它是所有的公钥, 不需要的引擎?

下面的行是错误的, pdecr_init 应该是 pencr_init 。 (当前在 OpenSSL 中, 它们都是 NULL。

315         EVP_PKEY_meth_set_encrypt(pmeth, pdecr_init, pkcs11_pkey_rsa_encrypt);
原文:

Why did you implement pkcs11_evp_rsa_encrypt? It is all public key and does not need the engine?

The below line is wrong, pdecr_init should be pencr_init. (Currently in OpenSSL they are both NULL.)

315         EVP_PKEY_meth_set_encrypt(pmeth, pdecr_init, pkcs11_pkey_rsa_encrypt);
dengert 2017-10-9
71

好的, 我看到哪里 = NULL 来自。pkeyutl. c 行300正在呼叫请求长度。
然后, 它再分配 buf_out 并调用 do_keyop 与缓冲区。

因此, 为了让这个工作, pkcs11_pkey_rsa_decrypt 需要认识到这只是一个查询,

这使事情复杂化, 因为 pkcs11_pkey_rsa_decrypt 做一个 C_DecryptInit, 也许一个 pin 提示,
才能确定从 C_Decrypt 的长度。

第一件事, 我会尝试在 pkcs11_pkey_rsa_decrypt, 如果它看到 = NULL, 转到 do_original。这可能让 OpenSSL 确定的长度, 而不做任何加密。 然后, 下一次调用 pkcs11_pkey_rsa_decrypt, 它将有出和 * outlen 设置, 只需要尝试一次 PKCS#11 代码, 或者最终返回结果, 如果它的工作或做一个转到 do_original。

如果这种方法不起作用, 那么它就变得棘手, 因为你只想做一次 C_DecryptInit, 而不是在每次调用 pkcs11_pkey_rsa_decrypt 的时候。因此, 一些国家将不得不保持。

它可以做 PKCS#11 调用的第一次通过, 并保存结果, 所以第二个出来! = NULL 所有它必须做的是 memcpy 的结果。但这取决于打电话的人总是做两个电话。

可能可以定义一个非 NULL pencr_init, 它也可以做一些事情。

原文:

OK I do see where out=NULL comes from. pkeyutl.c line 300 is calling to request the length.
It then allocates buf_out and calls do_keyop with the buffer again.

So to get this to work, the pkcs11_pkey_rsa_decrypt needs to recognize this is just a query,

This complicates things as pkcs11_pkey_rsa_decrypt does a C_DecryptInit and maybe a pin prompt,
before it can determine the length from C_Decrypt.

First thing I would try in pkcs11_pkey_rsa_decrypt if it sees out=NULL, goto do_original. That may let OpenSSL determine the length without doing any crypto. Then the next time pkcs11_pkey_rsa_decrypt is called, it will have out and *outlen set and only need to try the PKCS#11 code once and either end up return the result if it worked or doing a goto do_original.

If that approach does not work, then it gets tricky as you only want to do a C_DecryptInit once, not in each time the pkcs11_pkey_rsa_decrypt is called. So some state will have to be kept.

It could do al the PKCS#11 calls on the first pass, and save the result so the second out != NULL all it has to do is memcpy the result. But this depends on the caller always doing both calls.

It might be possible to define a non NULL pencr_init that could do something too.

mouse07410 2017-10-9
72

好的, 我看到哪里 = NULL 来自。pkeyutl. c 行300正在呼叫请求长度。
然后, 它再分配 buf_out 并调用 do_keyop 与缓冲区。

是的没错和一个问题是-OpenSSL 正在这样做加密以及当公钥是引擎提供的.

因此, 为了让这个工作, pkcs11_pkey_rsa_decrypt 需要认识到这只是一个查询..。

这就是我想做的

这使事情复杂化, 因为 pkcs11_pkey_rsa_decrypt 做一个 C_DecryptInit, 也许一个 pin 提示, 在它能确定长度从 C_Decrypt。

是的。但这不应该是个问题这个 two-step 的舞蹈是可以的。

第一件事, 我会尝试在 pkcs11_pkey_rsa_decrypt, 如果它看到 = NULL, 转到 do_original。这可能让 OpenSSL 确定的长度, 而不做任何加密。

我宁愿不另外, 我已经观察到 pkey_rsa_encrypt() 它确实不是在磁盘文件中没有该键时执行 "正确的事情", 而缓冲区 ptr 为 NULL。

如果这种方法不起作用, 那么它就变得棘手, 因为你只想做一次 C_DecryptInit, 而不是在每次调用 pkcs11_pkey_rsa_decrypt 的时候。因此, 一些国家将不得不保持。

我认为我不同意。没有国家需要保持。这两个请求是完全独立的, 从理论上讲, 两者并不需要遵循另一种要求。我可能会知道, 如果我最终决定要解密, 我可能需要什么大小的缓冲区, 或者我可能会明白, 不管发生什么情况, 出的都不会大于 1MB, 并提供缓冲区大小, 而无需费心询问实际需要的大小或.

简而言之, 没有国家可以保留。

它可以做所有的 PKCS#11 调用第一次通过, 并保存结果, 所以第二个出来! = NULL 所有它必须做的是 memcpy 的结果。

它可以。但我的不想这样做。

可能可以定义一个非 NULL pencr_init, 它也可以做一些事情。

是的。但现在, 它的服务的唯一目的是提供一个解决方案的 OpenSSL 失败, 以处理其自己的 two-step 舞蹈 (首先问长度, 然后分配缓冲区, 并做真正的 op) 时, 从发动机的关键。

"do_original" 概念是;如果我们不能在我们的日常工作中, 后退, 让 OpenSSL 尝试, 也许失败。不应修改任何参数。

总的来说, 我理解并同意。然而, 在 OpenSSL 行为中有一个明显的错误。它比等待 "官方" 的补救措施更简单 (也更快)。

我看不出原来的 pkey_rsa_decrypt 如何工作, 如果出 = NULL。但我没有运行调试器, 看看是否是这样。

我不确定它确实起作用了--因为当密钥可用时 (而不是在一个令牌上), OpenSSL做/需要它的 two-step 舞蹈。这就是为什么我认为我的额外代码处理 out==NULL 是必要的, 在所有这些地方。

*outlensize_tsizeCK_ULONG 。看起来代码可能只在字节的机器上工作。

我明白你的意思了您建议如何解决此问题?

我不会尝试做任何其他的 rsa 填充, 目前的工作。坚持让 OAEP 工作。

  1. 我想我得到OAEP 工作。它通过了我所有的测试。
  2. 因此, 我不明白为什么不添加琐碎的 PKCS1 填充支持 (也测试成功)。
原文:

OK I do see where out=NULL comes from. pkeyutl.c line 300 is calling to request the length.
It then allocates buf_out and calls do_keyop with the buffer again.

Yes exactly. And one problem is - OpenSSL is doing this for encrypt as well when the pubkey is engine-provided.

So to get this to work, the pkcs11_pkey_rsa_decrypt needs to recognize this is just a query...

Which is what I think I'm doing.

This complicates things as pkcs11_pkey_rsa_decrypt does a C_DecryptInit and maybe a pin prompt, before it can determine the length from C_Decrypt.

Yes. But it shouldn't be a problem. This two-step dance is OK.

First thing I would try in pkcs11_pkey_rsa_decrypt if it sees out=NULL, goto do_original. That may let OpenSSL determine the length without doing any crypto.

I'd rather not. Plus, I've already observed with pkey_rsa_encrypt() that it does not do the "right thing" when the key is not in a disk file, and the buffer ptr is NULL.

If that approach does not work, then it gets tricky as you only want to do a C_DecryptInit once, not in each time the pkcs11_pkey_rsa_decrypt is called. So some state will have to be kept.

I don't think I agree. No state needs to be kept. The two requests are completely independent, and theoretically one does not have to follow the other. I might just learn what size buffer I might need if I eventually decide to decrypt, or I might know that no matter what, the out won't be larger than 1MB and provide the buffer that size without bothering to ask for the actual size needed, or...

In short, no state to keep.

It could do all the PKCS#11 calls on the first pass, and save the result so the second out != NULL all it has to do is memcpy the result.

It could. But I really don't want to do that.

It might be possible to define a non NULL pencr_init that could do something too.

Yes. But for right now the only purpose it's serving is providing a workaround for the OpenSSL failure to deal with its own two-step dance (first ask for length, then allocate the buffer and do the op for real) when the key is taken from the engine.

The "do_original" concept is; if we can't do it in our routines, fall back and let OpenSSL try and maybe fail. No parameters should be modified.

In general I do understand and agree. Here, however, there's an obvious error in OpenSSL behavior. And it's simpler (and far quicker) to accommodate for it than wait for the "official" remedy.

I don't see how the original pkey_rsa_decrypt could work if out=NULL. But I have not run a debugger on it to see if that is the case.

I'm not sure at all it did work - because when the key is available (rather than being on a token), OpenSSL does not do/need its two-step dance. That's why I think my extra code for dealing with out==NULL is necessary in all of those places.

*outlen is a size_t but size is CK_ULONG. It looks like the code may only work on little-endian machines.

I see your point. How would you recommend addressing this?

I would not try and do any other rsa padding, that currently work. stick with getting OAEP working.

  1. I think I got OAEP working. It passed all my tests.
  2. Therefore I don't see why not add the trivial PKCS1 padding support (which was also tested successfully).
dengert 2017-10-9
73

好吧, 我给你我的意见, 你不同意大多数。祝你好运。

原文:

OK, I gave you my opinions and you don't agree with most of them. Good luck.

mouse07410 2017-10-9
74

好吧, 我给你我的意见, 你不同意大多数。祝你好运。

我想现在--在你的帮助下--代码处于工作状态。它执行正确的 rsa-PSS (签名和验证, rsa-OAEP (加密和解密), rsa-PKCS (签名, 验证, 加密, 解密)。

没有你的帮助, 我无法得到这段代码。我不想要么显得忘恩负义, 要么轻率拒绝建议。但请考虑:

  • 我们希望代码尽可能简单 (因为许多原因)。
  • 在多次调用的情况下, 我们不能依赖于调用方是一致的-又称请求输出缓冲区大小的调用可能不是跟随实际的加密/解密调用 (尽管一般情况下它可能应该)。
  • 我们在 OpenSSL 发现了一个问题。该键要么被授予 OpenSSL 作为文件, 要么一切由引擎处理。现在, 我们遇到了一个情况, 当该键在一个文件中是不是时, 但引擎仍然希望原始 pkey_rsa_decrypt() (或 pkey_rsa_encrypt() ) 执行一些工作。那是 OpenSSL 休息的地方我提出并测试的解决方法处理了这一失败。我认为成本违反了 "干净的原创概念"--值得让这个东西工作, 不管 OpenSSL 是否解决这个问题。

最后, 这里是演示脚本的结果-正如您看到的那样, 在两个"仅内部填充" 和 "仅原始-RSA" 令牌上, 都有 PSS、OAEP、PKCS1 的罚款:

$ ~/src/test-pkcs11.sh
Testing RSA-PSS on YubiHSM2
+ /Users/ur20980/openssl-1.1/bin/openssl dgst -engine pkcs11 -keyform engine -sign 'pkcs11:token=YubiHSM;id=%04%01;type=private' -out /tmp/t3200.dat.sigpss -sigopt rsa_padding_mode:pss -sha384 /tmp/t3200.dat
engine "pkcs11" set.
Enter PKCS#11 token PIN for YubiHSM:
+ /Users/ur20980/openssl-1.1/bin/openssl dgst -engine pkcs11 -keyform engine -verify 'pkcs11:token=YubiHSM;id=%04%01;type=public' -signature /tmp/t3200.dat.sigpss -sigopt rsa_padding_mode:pss -sha384 /tmp/t3200.dat
engine "pkcs11" set.
Enter PKCS#11 token PIN for YubiHSM:
Verified OK
+ set +x


Testing RSA-PSS on YubiKey NEO
+ /Users/ur20980/openssl-1.1/bin/openssl dgst -engine pkcs11 -keyform engine -sign 'pkcs11:token=Uri%20the%20Great;id=%02;type=private' -out /tmp/t3200.dat.sigpss -sigopt rsa_padding_mode:pss -sha384 /tmp/t3200.dat
engine "pkcs11" set.
Enter PKCS#11 token PIN for Uri the Great:
Enter PKCS#11 key PIN for SIGN key:
+ /Users/ur20980/openssl-1.1/bin/openssl dgst -engine pkcs11 -keyform engine -verify 'pkcs11:token=Uri%20the%20Great;id=%02;type=public' -signature /tmp/t3200.dat.sigpss -sigopt rsa_padding_mode:pss -sha384 /tmp/t3200.dat
engine "pkcs11" set.
Verified OK
+ set +x


Testing RSA-PKCS v1.5 Signature on YubiHSM2
+ /Users/ur20980/openssl-1.1/bin/openssl dgst -engine pkcs11 -keyform engine -sign 'pkcs11:token=YubiHSM;id=%04%01;type=private' -out /tmp/t3200.dat.sigpkcs -sigopt rsa_padding_mode:pkcs1 -sha384 /tmp/t3200.dat
engine "pkcs11" set.
Enter PKCS#11 token PIN for YubiHSM:
+ /Users/ur20980/openssl-1.1/bin/openssl dgst -engine pkcs11 -keyform engine -verify 'pkcs11:token=YubiHSM;id=%04%01;type=public' -signature /tmp/t3200.dat.sigpkcs -sigopt rsa_padding_mode:pkcs1 -sha384 /tmp/t3200.dat
engine "pkcs11" set.
Enter PKCS#11 token PIN for YubiHSM:
Verified OK
+ set +x


Testing RSA-PKCS v1.5 Signature on YubiKey NEO
+ /Users/ur20980/openssl-1.1/bin/openssl dgst -engine pkcs11 -keyform engine -sign 'pkcs11:token=Uri%20the%20Great;id=%02;type=private' -out /tmp/t3200.dat.sigpkcs -sigopt rsa_padding_mode:pkcs1 -sha384 /tmp/t3200.dat
engine "pkcs11" set.
Enter PKCS#11 token PIN for Uri the Great:
Enter PKCS#11 key PIN for SIGN key:
+ /Users/ur20980/openssl-1.1/bin/openssl dgst -engine pkcs11 -keyform engine -verify 'pkcs11:token=Uri%20the%20Great;id=%02;type=public' -signature /tmp/t3200.dat.sigpkcs -sigopt rsa_padding_mode:pkcs1 -sha384 /tmp/t3200.dat
engine "pkcs11" set.
Verified OK
+ set +x


Testing RSA-OAEP on YubiHSM2
+ /Users/ur20980/openssl-1.1/bin/openssl pkeyutl -engine pkcs11 -keyform engine -pubin -encrypt -inkey 'pkcs11:token=YubiHSM;id=%04%02;type=public' -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha384 -in /tmp/t1264.dat -out /tmp/t1264.dat.oaep
engine "pkcs11" set.
Enter PKCS#11 token PIN for YubiHSM:
+ /Users/ur20980/openssl-1.1/bin/openssl pkeyutl -engine pkcs11 -keyform engine -decrypt -inkey 'pkcs11:token=YubiHSM;id=%04%02;type=private' -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha384 -in /tmp/t1264.dat.oaep -out /tmp/t1264.dat.dec
engine "pkcs11" set.
Enter PKCS#11 token PIN for YubiHSM:
+ set +x
Decrypted file matched plaintext.


Testing RSA-OAEP on YubiKey NEO
+ /Users/ur20980/openssl-1.1/bin/openssl pkeyutl -engine pkcs11 -keyform engine -pubin -encrypt -inkey 'pkcs11:token=Uri%20the%20Great;id=%03;type=public' -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha384 -in /tmp/t1264.dat -out /tmp/t1264.dat.oaep
engine "pkcs11" set.
+ /Users/ur20980/openssl-1.1/bin/openssl pkeyutl -engine pkcs11 -keyform engine -decrypt -inkey 'pkcs11:token=Uri%20the%20Great;id=%03;type=private' -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha384 -in /tmp/t1264.dat.oaep -out /tmp/t1264.dat.dec
engine "pkcs11" set.
Enter PKCS#11 token PIN for Uri the Great:
+ set +x
Decrypted file matched plaintext.


Testing RSA-PKCS v1.5 on YubiHSM2
+ /Users/ur20980/openssl-1.1/bin/openssl pkeyutl -engine pkcs11 -keyform engine -pubin -encrypt -inkey 'pkcs11:token=YubiHSM;id=%04%02;type=public' -pkeyopt rsa_padding_mode:pkcs1 -in /tmp/t1264.dat -out /tmp/t1264.dat.pkcs
engine "pkcs11" set.
Enter PKCS#11 token PIN for YubiHSM:
+ /Users/ur20980/openssl-1.1/bin/openssl pkeyutl -engine pkcs11 -keyform engine -decrypt -inkey 'pkcs11:token=YubiHSM;id=%04%02;type=private' -pkeyopt rsa_padding_mode:pkcs1 -in /tmp/t1264.dat.pkcs -out /tmp/t1264.dat.dec
engine "pkcs11" set.
Enter PKCS#11 token PIN for YubiHSM:
+ set +x
Decrypted file matched plaintext.


Testing RSA-PKCS v1.5 on YubiKey NEO
+ /Users/ur20980/openssl-1.1/bin/openssl pkeyutl -engine pkcs11 -keyform engine -pubin -encrypt -inkey 'pkcs11:token=Uri%20the%20Great;id=%03;type=public' -pkeyopt rsa_padding_mode:pkcs1 -in /tmp/t1264.dat -out /tmp/t1264.dat.pkcs
engine "pkcs11" set.
+ /Users/ur20980/openssl-1.1/bin/openssl pkeyutl -engine pkcs11 -keyform engine -decrypt -inkey 'pkcs11:token=Uri%20the%20Great;id=%03;type=private' -pkeyopt rsa_padding_mode:pkcs1 -in /tmp/t1264.dat.pkcs -out /tmp/t1264.dat.dec
engine "pkcs11" set.
Enter PKCS#11 token PIN for Uri the Great:
+ set +x
Decrypted file matched plaintext.


$

我没有将所有的哈希 mgf 组合添加到我的测试脚本中, 但是我尝试了离线, 而不是上面显示的那样。一切都成功了

是否有任何 (角) 案件, 你认为应该检查/测试?

附言我要挖掘我的旧代码, 以编程方式访问标记, 并在没有 "pkeyutl" CLI 的时候查看它的行为。

@dengert我认为剩下的一个问题是如何模拟等 EVP_PKEY_meth_get_sign() OpenSSL-1.0.2。会喜欢的建议。

原文:

OK, I gave you my opinions and you don't agree with most of them. Good luck.

I think that by now - and with your help - the code is in working condition. It performs correctly RSA-PSS (signature and verification, RSA-OAEP (encryption and decryption), RSA-PKCS (signature, verification, encryption, decryption).

I wouldn't be able to get this code working without your help. I don't want to either appear ungrateful, or to flippantly reject suggestions. But please consider:

  • We want the code to be as simple as practical (for many reasons).
  • In case of multiple calls we cannot rely on the caller being consistent - aka a call to request output buffer size may not follow by the actual encryption/decryption call (though in general it probably should).
  • We uncovered a problem in OpenSSL. The key was either given to OpenSSL as a file, or everything was handled by the engine. Now, we encountered a situation when the key is not in a file, but the engine still wants the original pkey_rsa_decrypt() (or pkey_rsa_encrypt()) to do some work. That's where OpenSSL breaks. The workaround I proposed and tested deals with this failure. I consider the cost - violating the "clean do-original concept" - well-worth getting this thing to work regardless of whether OpenSSL does or does not fix this problem.

Finally, here's the result of the demo script - as you see it does PSS, OAEP, and PKCS1 fine on both "internal-padding-only" and "raw-RSA-only" tokens:

$ ~/src/test-pkcs11.sh
Testing RSA-PSS on YubiHSM2
+ /Users/ur20980/openssl-1.1/bin/openssl dgst -engine pkcs11 -keyform engine -sign 'pkcs11:token=YubiHSM;id=%04%01;type=private' -out /tmp/t3200.dat.sigpss -sigopt rsa_padding_mode:pss -sha384 /tmp/t3200.dat
engine "pkcs11" set.
Enter PKCS#11 token PIN for YubiHSM:
+ /Users/ur20980/openssl-1.1/bin/openssl dgst -engine pkcs11 -keyform engine -verify 'pkcs11:token=YubiHSM;id=%04%01;type=public' -signature /tmp/t3200.dat.sigpss -sigopt rsa_padding_mode:pss -sha384 /tmp/t3200.dat
engine "pkcs11" set.
Enter PKCS#11 token PIN for YubiHSM:
Verified OK
+ set +x


Testing RSA-PSS on YubiKey NEO
+ /Users/ur20980/openssl-1.1/bin/openssl dgst -engine pkcs11 -keyform engine -sign 'pkcs11:token=Uri%20the%20Great;id=%02;type=private' -out /tmp/t3200.dat.sigpss -sigopt rsa_padding_mode:pss -sha384 /tmp/t3200.dat
engine "pkcs11" set.
Enter PKCS#11 token PIN for Uri the Great:
Enter PKCS#11 key PIN for SIGN key:
+ /Users/ur20980/openssl-1.1/bin/openssl dgst -engine pkcs11 -keyform engine -verify 'pkcs11:token=Uri%20the%20Great;id=%02;type=public' -signature /tmp/t3200.dat.sigpss -sigopt rsa_padding_mode:pss -sha384 /tmp/t3200.dat
engine "pkcs11" set.
Verified OK
+ set +x


Testing RSA-PKCS v1.5 Signature on YubiHSM2
+ /Users/ur20980/openssl-1.1/bin/openssl dgst -engine pkcs11 -keyform engine -sign 'pkcs11:token=YubiHSM;id=%04%01;type=private' -out /tmp/t3200.dat.sigpkcs -sigopt rsa_padding_mode:pkcs1 -sha384 /tmp/t3200.dat
engine "pkcs11" set.
Enter PKCS#11 token PIN for YubiHSM:
+ /Users/ur20980/openssl-1.1/bin/openssl dgst -engine pkcs11 -keyform engine -verify 'pkcs11:token=YubiHSM;id=%04%01;type=public' -signature /tmp/t3200.dat.sigpkcs -sigopt rsa_padding_mode:pkcs1 -sha384 /tmp/t3200.dat
engine "pkcs11" set.
Enter PKCS#11 token PIN for YubiHSM:
Verified OK
+ set +x


Testing RSA-PKCS v1.5 Signature on YubiKey NEO
+ /Users/ur20980/openssl-1.1/bin/openssl dgst -engine pkcs11 -keyform engine -sign 'pkcs11:token=Uri%20the%20Great;id=%02;type=private' -out /tmp/t3200.dat.sigpkcs -sigopt rsa_padding_mode:pkcs1 -sha384 /tmp/t3200.dat
engine "pkcs11" set.
Enter PKCS#11 token PIN for Uri the Great:
Enter PKCS#11 key PIN for SIGN key:
+ /Users/ur20980/openssl-1.1/bin/openssl dgst -engine pkcs11 -keyform engine -verify 'pkcs11:token=Uri%20the%20Great;id=%02;type=public' -signature /tmp/t3200.dat.sigpkcs -sigopt rsa_padding_mode:pkcs1 -sha384 /tmp/t3200.dat
engine "pkcs11" set.
Verified OK
+ set +x


Testing RSA-OAEP on YubiHSM2
+ /Users/ur20980/openssl-1.1/bin/openssl pkeyutl -engine pkcs11 -keyform engine -pubin -encrypt -inkey 'pkcs11:token=YubiHSM;id=%04%02;type=public' -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha384 -in /tmp/t1264.dat -out /tmp/t1264.dat.oaep
engine "pkcs11" set.
Enter PKCS#11 token PIN for YubiHSM:
+ /Users/ur20980/openssl-1.1/bin/openssl pkeyutl -engine pkcs11 -keyform engine -decrypt -inkey 'pkcs11:token=YubiHSM;id=%04%02;type=private' -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha384 -in /tmp/t1264.dat.oaep -out /tmp/t1264.dat.dec
engine "pkcs11" set.
Enter PKCS#11 token PIN for YubiHSM:
+ set +x
Decrypted file matched plaintext.


Testing RSA-OAEP on YubiKey NEO
+ /Users/ur20980/openssl-1.1/bin/openssl pkeyutl -engine pkcs11 -keyform engine -pubin -encrypt -inkey 'pkcs11:token=Uri%20the%20Great;id=%03;type=public' -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha384 -in /tmp/t1264.dat -out /tmp/t1264.dat.oaep
engine "pkcs11" set.
+ /Users/ur20980/openssl-1.1/bin/openssl pkeyutl -engine pkcs11 -keyform engine -decrypt -inkey 'pkcs11:token=Uri%20the%20Great;id=%03;type=private' -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha384 -pkeyopt rsa_mgf1_md:sha384 -in /tmp/t1264.dat.oaep -out /tmp/t1264.dat.dec
engine "pkcs11" set.
Enter PKCS#11 token PIN for Uri the Great:
+ set +x
Decrypted file matched plaintext.


Testing RSA-PKCS v1.5 on YubiHSM2
+ /Users/ur20980/openssl-1.1/bin/openssl pkeyutl -engine pkcs11 -keyform engine -pubin -encrypt -inkey 'pkcs11:token=YubiHSM;id=%04%02;type=public' -pkeyopt rsa_padding_mode:pkcs1 -in /tmp/t1264.dat -out /tmp/t1264.dat.pkcs
engine "pkcs11" set.
Enter PKCS#11 token PIN for YubiHSM:
+ /Users/ur20980/openssl-1.1/bin/openssl pkeyutl -engine pkcs11 -keyform engine -decrypt -inkey 'pkcs11:token=YubiHSM;id=%04%02;type=private' -pkeyopt rsa_padding_mode:pkcs1 -in /tmp/t1264.dat.pkcs -out /tmp/t1264.dat.dec
engine "pkcs11" set.
Enter PKCS#11 token PIN for YubiHSM:
+ set +x
Decrypted file matched plaintext.


Testing RSA-PKCS v1.5 on YubiKey NEO
+ /Users/ur20980/openssl-1.1/bin/openssl pkeyutl -engine pkcs11 -keyform engine -pubin -encrypt -inkey 'pkcs11:token=Uri%20the%20Great;id=%03;type=public' -pkeyopt rsa_padding_mode:pkcs1 -in /tmp/t1264.dat -out /tmp/t1264.dat.pkcs
engine "pkcs11" set.
+ /Users/ur20980/openssl-1.1/bin/openssl pkeyutl -engine pkcs11 -keyform engine -decrypt -inkey 'pkcs11:token=Uri%20the%20Great;id=%03;type=private' -pkeyopt rsa_padding_mode:pkcs1 -in /tmp/t1264.dat.pkcs -out /tmp/t1264.dat.dec
engine "pkcs11" set.
Enter PKCS#11 token PIN for Uri the Great:
+ set +x
Decrypted file matched plaintext.


$

I did not add all the hash-mgf combinations to my test-script, but I tried offline rather more than is shown above. Everything worked.

Are there any (corner) cases that you think should be checked/tested?

P.S. I'm about to dig my old code that accesses tokens programmatically, and see how it behaves when there's no "pkeyutl" CLI.

P.P.S. @dengert the one problem I think is remaining is how to emulate EVP_PKEY_meth_get_sign() and such on OpenSSL-1.0.2. Would appreciate suggestions.

mouse07410 2017-10-9
75

启用 openssl rsautl -oaep . . . :

$ yhsm2-rsa-encr-demo2 
Generate a random data file (1000 bytes), Base64-encoded...
openssl rand -base64 -out /tmp/derive.78286.text 1000

Generated
  key: 6a5df87f21adb48a835ae3ea4822e299c7531f6eb7b9bfe374feee8dfa5562ef
  iv:  1dac0e2ab852c55e7995f43398551590

Encrypt file /tmp/derive.78286.text with this key and IV...
openssl enc -aes-256-cfb -a -e -in /tmp/derive.78286.text -out /tmp/derive.78286.text.enc -K 6a5df87f21adb48a835ae3ea4822e299c7531f6eb7b9bfe374feee8dfa5562ef -iv 1dac0e2ab852c55e7995f43398551590

Encrypting this random symmetric key to token RSA KEY MAN key...
echo 6a5df87f21adb48a835ae3ea4822e299c7531f6eb7b9bfe374feee8dfa5562ef | xxd -r -p -c 200 | ~/openssl-1.1/bin/openssl rsautl -engine pkcs11 -keyform engine -encrypt -pubin -inkey "pkcs11:token=YubiHSM;id=%04%02;type=public" -oaep -out /tmp/derive.78286.key.enc
engine "pkcs11" set.
Enter PKCS#11 token PIN for YubiHSM:

Decrypting the symmetric key on the token...
~/openssl-1.1/bin/openssl rasutl -engine pkcs11 -keyform engine -decrypt -inkey "pkcs11:token=YubiHSM;id=%04%02;type=private" -oaep -in /tmp/derive.78286.key.enc | xxd -p -c 200
engine "pkcs11" set.
Enter PKCS#11 token PIN for YubiHSM:

Decrypt file /tmp/derive.78286.text.enc with this key and IV...
openssl enc -aes-256-cfb -a -d -in /tmp/derive.78286.text.enc -out /tmp/derive.78286.text.dec -K 6a5df87f21adb48a835ae3ea4822e299c7531f6eb7b9bfe374feee8dfa5562ef -iv 1dac0e2ab852c55e7995f43398551590

KEY1="6a5df87f21adb48a835ae3ea4822e299c7531f6eb7b9bfe374feee8dfa5562ef"
KEY2="6a5df87f21adb48a835ae3ea4822e299c7531f6eb7b9bfe374feee8dfa5562ef"
Original and decrypted keys  match
Original and decrypted files match
$

上述 ( rsautl -oaep ) 在进行此更改之前没有使用普通的 PIV 设备, 并且它仍然不起作用。由于 pkeyutl . . . -pkeyopt rsa_padding_mode:oaep 与 PIV 一起工作, 我认为我们可以离开 rsautl ..。

原文:

Enabling openssl rsautl -oaep . . .:

$ yhsm2-rsa-encr-demo2 
Generate a random data file (1000 bytes), Base64-encoded...
openssl rand -base64 -out /tmp/derive.78286.text 1000

Generated
  key: 6a5df87f21adb48a835ae3ea4822e299c7531f6eb7b9bfe374feee8dfa5562ef
  iv:  1dac0e2ab852c55e7995f43398551590

Encrypt file /tmp/derive.78286.text with this key and IV...
openssl enc -aes-256-cfb -a -e -in /tmp/derive.78286.text -out /tmp/derive.78286.text.enc -K 6a5df87f21adb48a835ae3ea4822e299c7531f6eb7b9bfe374feee8dfa5562ef -iv 1dac0e2ab852c55e7995f43398551590

Encrypting this random symmetric key to token RSA KEY MAN key...
echo 6a5df87f21adb48a835ae3ea4822e299c7531f6eb7b9bfe374feee8dfa5562ef | xxd -r -p -c 200 | ~/openssl-1.1/bin/openssl rsautl -engine pkcs11 -keyform engine -encrypt -pubin -inkey "pkcs11:token=YubiHSM;id=%04%02;type=public" -oaep -out /tmp/derive.78286.key.enc
engine "pkcs11" set.
Enter PKCS#11 token PIN for YubiHSM:

Decrypting the symmetric key on the token...
~/openssl-1.1/bin/openssl rasutl -engine pkcs11 -keyform engine -decrypt -inkey "pkcs11:token=YubiHSM;id=%04%02;type=private" -oaep -in /tmp/derive.78286.key.enc | xxd -p -c 200
engine "pkcs11" set.
Enter PKCS#11 token PIN for YubiHSM:

Decrypt file /tmp/derive.78286.text.enc with this key and IV...
openssl enc -aes-256-cfb -a -d -in /tmp/derive.78286.text.enc -out /tmp/derive.78286.text.dec -K 6a5df87f21adb48a835ae3ea4822e299c7531f6eb7b9bfe374feee8dfa5562ef -iv 1dac0e2ab852c55e7995f43398551590

KEY1="6a5df87f21adb48a835ae3ea4822e299c7531f6eb7b9bfe374feee8dfa5562ef"
KEY2="6a5df87f21adb48a835ae3ea4822e299c7531f6eb7b9bfe374feee8dfa5562ef"
Original and decrypted keys  match
Original and decrypted files match
$

The above (rsautl -oaep) did not work with a normal PIV device before this change, and it still doesn't work with it. Since pkeyutl . . . -pkeyopt rsa_padding_mode:oaep does work with PIV, I think we can leave rsautl as is...?

mouse07410 2017-10-9
76

@mtrojnar请您澄清一下: 您是否希望新的函数实现 rsa-PSS 和 rsa-OAEP (如 pkcs11_pkey_rsa_sign() ) 从移动 src/p11_rsa.csrc/p11_pkey.c

原文:

@mtrojnar could you clarify please: do you want new functions that implement RSA-PSS and RSA-OAEP (like pkcs11_pkey_rsa_sign()) moved from src/p11_rsa.c to src/p11_pkey.c?

mtrojnar 2017-10-9
77

我希望所有其余的代码目前分散在 eng_front 和 p11_rsa 之间, 将被移入 p11_pkey. c。

原文:

I want all the remaining code currently scattered between eng_front.c and p11_rsa.c to be moved into p11_pkey.c.

dengert 2017-10-9
78

我看过你 OpenSSL 的错误报告事实上, 似乎 evp_pkey_rsa_decrypt 不处理 = NULL。 错误报告说 "通常不应该发生", 但:
https://www.openssl.org/docs/man1.0.2/crypto/EVP_PKEY_decrypt.html
表示: "如果出为 NULL, 则输出缓冲区的最大大小将写入 outlen 参数。
版本1.1 的文档有类似的措辞, EVP_PKEY_verify_recover, EVP_PKEY_sign, EVP_PKEY_encrypt, EVP_PKEY_derive。
因此, 它不是一个问题与 "正常", 但是一个 bug, 如果 EVP_PKEY_ * 例程不处理 = NULL。 这是不清楚的, 如果它只是一个问题与 OAEP, 这是你发现的情况。

向 OpenSSL 的开发者展示, 它不是一个引擎问题, 而是一个 OpenSSL 的问题, 可以删除 pkeyutil。

296     if (kdflen != 0) {
297         buf_outlen = kdflen;
298         rv = 1;
299     } else {
...
302     }

这将导致 OAEP 没有引擎而失败。可用于测试 EVP_PKEY_verify_recover、EVP_PKEY_sign、EVP_PKEY_encrypt、EVP_PKEY_derive 和其他关键类型。所有密钥类型都应支持返回 "输出缓冲区的最大大小" (如文档所述)。

在此期间, 直到他们修复 OpenSSL, 你可以处理出 = 空在 pkcs11_pkey_rsa _ * 例程使用类似于您所描述的代码:

  if (out == NULL) {
       int klen = RSA_size(ctx->pkey->pkey.rsa);
       *outlen = klen;
       return 1;
 }

这将调用 do_original, 因为您在引擎代码中通过调整 "输出缓冲区的最大大小" (基于 RSA 密钥大小) 来处理它。

这将让你的 libp11 mods 的工作与未修改的 OpenSSL。

原文:

I read your OpenSSL bug report. and indeed it appears that the evp_pkey_rsa_decrypt does not handle out=NULL. The bug report says "Normally it should not happen" But:
https://www.openssl.org/docs/man1.0.2/crypto/EVP_PKEY_decrypt.html
says: " If out is NULL then the maximum size of the output buffer is written to the outlen parameter."
The version 1.1 docs have similar wording for EVP_PKEY_verify_recover, EVP_PKEY_sign, EVP_PKEY_encrypt, EVP_PKEY_derive.
So it is not an issue with "normally" but is a bug if the EVP_PKEY_* routines do not handle out=NULL. It is not clear if it is only an issue with OAEP, which is the case you found.

To show to OpenSSL developers that it is not an engine problem but an OpenSSL problem one could remove in pkeyutil.c

296     if (kdflen != 0) {
297         buf_outlen = kdflen;
298         rv = 1;
299     } else {
...
302     }

This should cause OAEP to fail without an engine. And could be used to test the EVP_PKEY_verify_recover, EVP_PKEY_sign, EVP_PKEY_encrypt, EVP_PKEY_derive and with other key types. All key types should support returning "maximum size of the output buffer" as documented.

And in the meantime until they fix OpenSSL, you could handle the out=NULL in the pkcs11_pkey_rsa_* routines using the code similar to what you described:

  if (out == NULL) {
       int klen = RSA_size(ctx->pkey->pkey.rsa);
       *outlen = klen;
       return 1;
 }

This would then not call the do_original, because you are handling it in the engine code by retuning the "maximum size of the output buffer" which is based on the RSA key size.

This would then let your libp11 mods work with unmodified OpenSSL.

mouse07410 2017-10-9
79

我看过你 OpenSSL 的错误报告而且确实出现 evp_pkey_rsa_decrypt 不处理 out=NULL

是的。然而, OpenSSL 开发团队认为, 错误的功能是 "低级" 的代码, 不应该直接调用, 所以它是 EVP_PKEY_... 函数的责任来处理 NULL 参数情况。虽然我不同意他们的立场, 并相信即使这是真的, 两个保护机制不会伤害-我不认为这是我可以赢得的战斗, 所以甚至不会尝试它。libp11 的问题对我来说已经够好了, 至少现在是这样。我此修补程序应该在 libp11, 无论 OpenSSL 团队是否在这个问题上改变了主意。

但我现在有一个不同的问题。OpenSSL CLI "dgst" 和 "pkeyutl" 都工作正常。下面是一个示例:

$ ~/openssl-1.1/bin/openssl pkeyutl -engine pkcs11 -keyform engine -encrypt -in t27.txt -out t27.txt.oaep -pubin -inkey "pkcs11:token=YubiHSM;id=%04%02;type=public" -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_mgf1_md:sha256 -pkeyopt rsa_oaep_md:sha256
engine "pkcs11" set.
Enter PKCS#11 token PIN for YubiHSM:
pkcs11_pkey_rsa_encrypt(): out=0x0 *outlen=1833709100  in=0x7fbb27f05000 inlen=27
pkcs11_pkey_rsa_encrypt(): out=0x7fbb27f057b0 *outlen=512  in=0x7fbb27f05000 inlen=27
$ ~/openssl-1.1/bin/openssl pkeyutl -engine pkcs11 -keyform engine -decrypt -in t27.txt.oaep -inkey "pkcs11:token=YubiHSM;id=%04%02;type=private" -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_mgf1_md:sha256 -pkeyopt rsa_oaep_md:sha256
engine "pkcs11" set.
Enter PKCS#11 token PIN for YubiHSM:
Entered pkcs11_pkey_rsa_decrypt() out=0x0  *outlen=1833709100 in=0x7fc1c0804b90 inlen=512
RSA_OAEP
hashAlg=SHA256 mgf=MGF1-SHA256 
Entered pkcs11_pkey_rsa_decrypt() out=0x7fc1bec1bc60  *outlen=27 in=0x7fc1c0804b90 inlen=512
RSA_OAEP
hashAlg=SHA256 mgf=MGF1-SHA256 
12345678901234567890123456
$ cat t27.txt
12345678901234567890123456
$ 

但是, 当 Im 尝试以编程方式完成相同的结果时, 代码的行为就好像 "挂钩" 未注册一样:

$ /tmp/OSSL-Tst3.dst/Users/ur20980/bin/OSSL-Tst3 
Using YubiHSM device...

Generated random 256-bit AES key:
6c 23 b8 0e ff e9 49 1c bb 61 b7 24 c6 b2 fc 72 
9e a4 03 fc 7d 5b 54 4c 3f cc 33 cf 83 f0 b5 6a 

Enter PKCS#11 token PIN for YubiHSM:
Symmetric key encrypted with RSA using RSA-OAEP padding (512 bytes):
5d 36 21 8d 1d 5a b1 b7 43 18 bf 54 52 5a 9d 9f 
. . . . .
a3 b7 09 cf 32 68 fc db 05 9b 87 e5 eb a5 6b 5f 

unwrap: loaded privkey of size 512
unwrap: allocating 512 bytes...
unwrap: failed to decrypt (rv=-1)
140735726228416:error:82079070:PKCS#11 module:pkcs11_private_decrypt:Mechanism invalid:p11_rsa.c:188:
Decryption failed! (rv=-1 olen=512)

OpenSSL crypto demo completed with errors!
$ 

它在最后一次检查 rvsrc/p11_rsa.c 文件中 pkcs11_private_decrypt() 失败, 但我认为这是 C_DecryptInit() 失败。问题是为什么-因为它的工作与 "pkeyutl"。

下面是 unwrap 方法的源代码 (为了简洁起见, 删除了错误检查, 直到最后一次解密之后, 它们都不会触发):

int unwrap(const unsigned char *in, const size_t inlen, unsigned char **out, size_t *olen, ENGINE *e, const int padding) {
    int            rv      = -1;
    EVP_PKEY      *privkey = NULL;
    EVP_PKEY_CTX  *ctx     = NULL;
    PW_CB_DATA     cb_data;
    
    cb_data.password = NULL;
    cb_data.prompt_info = "PIN:"; 
    
    privkey = ENGINE_load_private_key(e, KeyManPrivKey, NULL, &cb_data);
    printf("unwrap: loaded privkey of size %1d\n", EVP_PKEY_size(privkey));
    ctx = EVP_PKEY_CTX_new(privkey, NULL);
    EVP_PKEY_free(privkey);
    rv = EVP_PKEY_decrypt_init(ctx);
    if (rv <= 0) goto end;
    rv = EVP_PKEY_CTX_set_rsa_padding(ctx, padding);
    *olen = 0;
    rv = EVP_PKEY_decrypt(ctx, NULL, olen, in, inlen);
    *out = OPENSSL_malloc(*olen);
    printf("unwrap: allocating %1lu bytes...\n", *olen);
    rv = EVP_PKEY_decrypt(ctx, *out, olen, in, inlen);
    if (rv <= 0) {
        OPENSSL_free(*out); *out = NULL;
        fprintf(stderr, "unwrap: failed to decrypt (rv=%d)\n", rv);
        goto end;
    }
    printf("unwrap: decrypt returned %d (%1lu bytes)\n", rv, *olen);

end:
    ERR_print_errors_fp(stderr);
    if (ctx != NULL)
        EVP_PKEY_CTX_free(ctx);
    return rv;
}

当在调试器下运行 (我不得不写我的程序, 并加载它在苹果 Xcode IDE 能够使用调试器-但我已经做到了!:) 它经历了

  • 打开 ()
  • EVP_PKEY_decrypt ()
  • pkey_rsa_decrypt ()
  • RSA_private_decrypt (inlen, 在, rctx-> tbuf, 酰-> pkey-> pkey. rsa, RSA_NO_PADDING) 在 rsa_pmeth. c 行353
  • rsa > 冰毒 > rsa_priv_dec () 在 rsa_crpt. c 线43返回-1

生成以下输出:

. . . . .
unwrap: loaded privkey of size 512
unwrap: allocating 512 bytes...
unwrap: failed to decrypt (rv=-1)
4302398400:error:82079070:PKCS#11 module:pkcs11_private_decrypt:Mechanism invalid:p11_rsa.c:188:
Decryption failed! (rv=-1 olen=512)
(lldb) 

它看起来像引擎从来没有绑定这些 pkcs11_pkey_rsa_...() 方法。我试着检查错误的引擎是否被加载, 但它似乎是正确的使用。下面是加载引擎的代码 (为了简洁起见, 删除了错误检查):

ENGINE* load_engine(const char *engine_name) {
    ENGINE *e = NULL;
    
    ENGINE_load_rdrand();
    e = ENGINE_by_id("pkcs11");
    if ( ! ENGINE_init(e) )     return NULL;

    return e;
}

更新
我的代码用来做的是:

  • 负载引擎;
  • 创建 EVP_PKEY_CTX 用于加密、加密、自由上下文;
  • 创建 EVP_PKEY_CTX 用于解密、解密、自由上下文;
  • 创建 EVP_PKEY_CTX 用于签名、签名、自由上下文;
  • . . .

它与 Yubikey NEO 一起工作, 但在 HSM 中失败了。

我观察到, 如果我在不同的操作之间卸载和重新引擎, 即:

  • 负载引擎, 创建 EVP_PKEY_CTX 加密, 做加密, 自由上下文, 卸载引擎;
  • 加载引擎, 创建 EVP_PKEY_CTX 进行解密, 进行解密, 释放上下文, 卸载引擎;
  • . . .

它按预期方式工作.它工作了几次, 然后我开始得到错误:

p11-kit: p11-kit-trust: module failed to initialize, skipping: The module has already been initialized
p11-kit: opensc: module failed to initialize, skipping: The module has already been initialized
p11-kit: softhsm2: module failed to initialize, skipping: The module has already been initialized
p11-kit: yhsm2: module failed to initialize, skipping: The module has already been initialized
p11-kit: ykcs11: module failed to initialize, skipping: The module has already been initialized
Failed to enumerate slots
p11-kit: p11-kit-trust: module failed to initialize, skipping: The module has already been initialized
p11-kit: opensc: module failed to initialize, skipping: The module has already been initialized
p11-kit: softhsm2: module failed to initialize, skipping: The module has already been initialized
p11-kit: yhsm2: module failed to initialize, skipping: The module has already been initialized
p11-kit: ykcs11: module failed to initialize, skipping: The module has already been initialized
Failed to enumerate slots
PKCS11_get_private_key returned NULL
unwrap: failed to get handle to Decryption privkey "pkcs11:manufacturer=piv_II;id=%03;type=private"
140735726228416:error:80067065:pkcs11 engine:ctx_load_privkey:object not found:eng_back.c:884:
140735726228416:error:26096080:engine routines:ENGINE_load_private_key:failed loading private key:crypto/engine/eng_pkey.c:78:
Decryption failed! (rv=-1 olen=0)
crypto/engine/eng_init.c:66: OpenSSL internal error: refcount error
Abort trap: 6

在坠机报告中:

Exception Type:        EXC_CRASH (SIGABRT)
Exception Codes:       0x0000000000000000, 0x0000000000000000
Exception Note:        EXC_CORPSE_NOTIFY

Application Specific Information:
abort() called

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   libsystem_kernel.dylib        	0x00007fff8e192d42 __pthread_kill + 10
1   libsystem_pthread.dylib       	0x00007fff8e280457 pthread_kill + 90
2   libsystem_c.dylib             	0x00007fff8e0f8420 abort + 129
3   libcrypto.1.1.dylib           	0x0000000100ae9924 OPENSSL_die + 52
4   libcrypto.1.1.dylib           	0x0000000100b6d036 engine_unlocked_finish + 214 (eng_init.c:66)
5   libcrypto.1.1.dylib           	0x0000000100b6d1da ENGINE_finish + 74 (eng_init.c:101)
6   OSSL-Tst3                     	0x0000000100a44cf5 unload_engine + 21 (main.c:229)
7   OSSL-Tst3                     	0x0000000100a43606 main + 1750 (main.c:196)
8   libdyld.dylib                 	0x00007fff8e064235 start + 1

这是正确的行为吗?我做错什么了吗?我希望我不需要重新引擎来执行一大堆操作???

原文:

I read your OpenSSL bug report. and indeed it appears that the evp_pkey_rsa_decrypt does not handle out=NULL.

Yes. However, OpenSSL dev team holds the opinion that the faulty functions are the "lower level" code and not supposed to be called directly, so it's the EVP_PKEY_... functions' responsibility to handle the NULL argument case. While I disagree with their position, and believe that even if it were true, two protection mechanisms wouldn't hurt - I don't think that's the battle I can win, so won't even try it. Fixing the problem in libp11 is good enough for me, at least for now. And IMHO this fix should be in libp11 regardless of whether OpenSSL team does or does not change its mind on this issue.

But I have a different problem now. OpenSSL CLI "dgst" and "pkeyutl" both work fine. Here's an example:

$ ~/openssl-1.1/bin/openssl pkeyutl -engine pkcs11 -keyform engine -encrypt -in t27.txt -out t27.txt.oaep -pubin -inkey "pkcs11:token=YubiHSM;id=%04%02;type=public" -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_mgf1_md:sha256 -pkeyopt rsa_oaep_md:sha256
engine "pkcs11" set.
Enter PKCS#11 token PIN for YubiHSM:
pkcs11_pkey_rsa_encrypt(): out=0x0 *outlen=1833709100  in=0x7fbb27f05000 inlen=27
pkcs11_pkey_rsa_encrypt(): out=0x7fbb27f057b0 *outlen=512  in=0x7fbb27f05000 inlen=27
$ ~/openssl-1.1/bin/openssl pkeyutl -engine pkcs11 -keyform engine -decrypt -in t27.txt.oaep -inkey "pkcs11:token=YubiHSM;id=%04%02;type=private" -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_mgf1_md:sha256 -pkeyopt rsa_oaep_md:sha256
engine "pkcs11" set.
Enter PKCS#11 token PIN for YubiHSM:
Entered pkcs11_pkey_rsa_decrypt() out=0x0  *outlen=1833709100 in=0x7fc1c0804b90 inlen=512
RSA_OAEP
hashAlg=SHA256 mgf=MGF1-SHA256 
Entered pkcs11_pkey_rsa_decrypt() out=0x7fc1bec1bc60  *outlen=27 in=0x7fc1c0804b90 inlen=512
RSA_OAEP
hashAlg=SHA256 mgf=MGF1-SHA256 
12345678901234567890123456
$ cat t27.txt
12345678901234567890123456
$ 

But when Im trying to accomplish the same result programmatically, the code behaves as if the "hooks" are not registered:

$ /tmp/OSSL-Tst3.dst/Users/ur20980/bin/OSSL-Tst3 
Using YubiHSM device...

Generated random 256-bit AES key:
6c 23 b8 0e ff e9 49 1c bb 61 b7 24 c6 b2 fc 72 
9e a4 03 fc 7d 5b 54 4c 3f cc 33 cf 83 f0 b5 6a 

Enter PKCS#11 token PIN for YubiHSM:
Symmetric key encrypted with RSA using RSA-OAEP padding (512 bytes):
5d 36 21 8d 1d 5a b1 b7 43 18 bf 54 52 5a 9d 9f 
. . . . .
a3 b7 09 cf 32 68 fc db 05 9b 87 e5 eb a5 6b 5f 

unwrap: loaded privkey of size 512
unwrap: allocating 512 bytes...
unwrap: failed to decrypt (rv=-1)
140735726228416:error:82079070:PKCS#11 module:pkcs11_private_decrypt:Mechanism invalid:p11_rsa.c:188:
Decryption failed! (rv=-1 olen=512)

OpenSSL crypto demo completed with errors!
$ 

It fails in the src/p11_rsa.c file in pkcs11_private_decrypt() at the last check of rv, but I think it's C_DecryptInit() failure. The question is why - since it works with "pkeyutl".

Here's the source of the unwrap method (error checks removed for brevity - none of them fires anyway, until the very last decryption):

int unwrap(const unsigned char *in, const size_t inlen, unsigned char **out, size_t *olen, ENGINE *e, const int padding) {
    int            rv      = -1;
    EVP_PKEY      *privkey = NULL;
    EVP_PKEY_CTX  *ctx     = NULL;
    PW_CB_DATA     cb_data;
    
    cb_data.password = NULL;
    cb_data.prompt_info = "PIN:"; 
    
    privkey = ENGINE_load_private_key(e, KeyManPrivKey, NULL, &cb_data);
    printf("unwrap: loaded privkey of size %1d\n", EVP_PKEY_size(privkey));
    ctx = EVP_PKEY_CTX_new(privkey, NULL);
    EVP_PKEY_free(privkey);
    rv = EVP_PKEY_decrypt_init(ctx);
    if (rv <= 0) goto end;
    rv = EVP_PKEY_CTX_set_rsa_padding(ctx, padding);
    *olen = 0;
    rv = EVP_PKEY_decrypt(ctx, NULL, olen, in, inlen);
    *out = OPENSSL_malloc(*olen);
    printf("unwrap: allocating %1lu bytes...\n", *olen);
    rv = EVP_PKEY_decrypt(ctx, *out, olen, in, inlen);
    if (rv <= 0) {
        OPENSSL_free(*out); *out = NULL;
        fprintf(stderr, "unwrap: failed to decrypt (rv=%d)\n", rv);
        goto end;
    }
    printf("unwrap: decrypt returned %d (%1lu bytes)\n", rv, *olen);

end:
    ERR_print_errors_fp(stderr);
    if (ctx != NULL)
        EVP_PKEY_CTX_free(ctx);
    return rv;
}

When running under debugger (I had to write my program and load it in Apple Xcode IDE to be able to use a debugger - but I've done it! :) it went through

  • unwrap()
  • EVP_PKEY_decrypt()
  • pkey_rsa_decrypt()
  • RSA_private_decrypt(inlen, in, rctx->tbuf, ctx->pkey->pkey.rsa, RSA_NO_PADDING) in rsa_pmeth.c line 353
  • rsa->meth->rsa_priv_dec() in rsa_crpt.c line 43 returning -1

producing the following output:

. . . . .
unwrap: loaded privkey of size 512
unwrap: allocating 512 bytes...
unwrap: failed to decrypt (rv=-1)
4302398400:error:82079070:PKCS#11 module:pkcs11_private_decrypt:Mechanism invalid:p11_rsa.c:188:
Decryption failed! (rv=-1 olen=512)
(lldb) 

It looks like the engine never bound those pkcs11_pkey_rsa_...() methods. I tried to check whether the wrong engine got loaded, but it appears that the correct one is used. Here's the code that loads the engine (error checks removed for brevity):

ENGINE* load_engine(const char *engine_name) {
    ENGINE *e = NULL;
    
    ENGINE_load_rdrand();
    e = ENGINE_by_id("pkcs11");
    if ( ! ENGINE_init(e) )     return NULL;

    return e;
}

Update
What my code used to do was:

  • Load engine;
  • Create EVP_PKEY_CTX for encryption, do encryption, free context;
  • Create EVP_PKEY_CTX for decryption, do decryption, free context;
  • Create EVP_PKEY_CTX for signing, do signing, free context;
  • . . .

And it worked with Yubikey NEO, but failed with HSM.

I observed that if I unload and re-load the engine between different operations, i.e.:

  • Load engine, create EVP_PKEY_CTX for encryption, do encryption, free context, unload engine;
  • Load engine, create EVP_PKEY_CTX for decryption, do decryption, free context, unload engine;
  • . . .

It works as expected. It worked couple of times, then I started to get errors:

p11-kit: p11-kit-trust: module failed to initialize, skipping: The module has already been initialized
p11-kit: opensc: module failed to initialize, skipping: The module has already been initialized
p11-kit: softhsm2: module failed to initialize, skipping: The module has already been initialized
p11-kit: yhsm2: module failed to initialize, skipping: The module has already been initialized
p11-kit: ykcs11: module failed to initialize, skipping: The module has already been initialized
Failed to enumerate slots
p11-kit: p11-kit-trust: module failed to initialize, skipping: The module has already been initialized
p11-kit: opensc: module failed to initialize, skipping: The module has already been initialized
p11-kit: softhsm2: module failed to initialize, skipping: The module has already been initialized
p11-kit: yhsm2: module failed to initialize, skipping: The module has already been initialized
p11-kit: ykcs11: module failed to initialize, skipping: The module has already been initialized
Failed to enumerate slots
PKCS11_get_private_key returned NULL
unwrap: failed to get handle to Decryption privkey "pkcs11:manufacturer=piv_II;id=%03;type=private"
140735726228416:error:80067065:pkcs11 engine:ctx_load_privkey:object not found:eng_back.c:884:
140735726228416:error:26096080:engine routines:ENGINE_load_private_key:failed loading private key:crypto/engine/eng_pkey.c:78:
Decryption failed! (rv=-1 olen=0)
crypto/engine/eng_init.c:66: OpenSSL internal error: refcount error
Abort trap: 6

and in the crash report:

Exception Type:        EXC_CRASH (SIGABRT)
Exception Codes:       0x0000000000000000, 0x0000000000000000
Exception Note:        EXC_CORPSE_NOTIFY

Application Specific Information:
abort() called

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   libsystem_kernel.dylib        	0x00007fff8e192d42 __pthread_kill + 10
1   libsystem_pthread.dylib       	0x00007fff8e280457 pthread_kill + 90
2   libsystem_c.dylib             	0x00007fff8e0f8420 abort + 129
3   libcrypto.1.1.dylib           	0x0000000100ae9924 OPENSSL_die + 52
4   libcrypto.1.1.dylib           	0x0000000100b6d036 engine_unlocked_finish + 214 (eng_init.c:66)
5   libcrypto.1.1.dylib           	0x0000000100b6d1da ENGINE_finish + 74 (eng_init.c:101)
6   OSSL-Tst3                     	0x0000000100a44cf5 unload_engine + 21 (main.c:229)
7   OSSL-Tst3                     	0x0000000100a43606 main + 1750 (main.c:196)
8   libdyld.dylib                 	0x00007fff8e064235 start + 1

Is this the correct behavior? Am I doing something wrong? I hoped I don't need to re-load the engine to perform a whole bunch of operations???

dengert 2017-10-9
80

从 OpenSSL 开发人员的电子邮件, 它看起来像在 eng_front. c:
297!(pmeth = EVP_PKEY_meth_new (EVP_PKEY_RSA, 0)))
应该是
297!(pmeth = EVP_PKEY_meth_new (EVP_PKEY_RSA, EVP_PKEY_FLAG_AUTOARGLEN)))

这将导致在加密/副总裁/pmeth_fn. c:
#define M_check_autoarg (酰、arg、arglen、err)
要处理掉 = = = NULL。
我会有, 虽然 EVP_PKEY_meth_copy (pmeth, orig_evp_pkey_meth_rsa) 将
也复制了旗子

如果该方法有效, 则在引擎代码中对出的更改为 = NULL。

原文:

From the OpenSSL developers e-mail, It looks like the line in eng_front.c:
297 !(pmeth = EVP_PKEY_meth_new(EVP_PKEY_RSA, 0)))
should be
297 !(pmeth = EVP_PKEY_meth_new(EVP_PKEY_RSA, EVP_PKEY_FLAG_AUTOARGLEN)))

That will cause the macro in crypto/evp/pmeth_fn.c:
#define M_check_autoarg(ctx, arg, arglen, err)
to take care of out==NULL.
I would have though that EVP_PKEY_meth_copy(pmeth, orig_evp_pkey_meth_rsa) would
have copied the flags too.

If that works, the change for out==NULL is all in the engine code.

dengert 2017-10-9
81

你说: "我观察到, 如果我卸载和重新在不同的操作之间的引擎, 即:"

我认为你不应该那样做。您松开所有的 PKCS#11 对象、会话、加载的密钥等, 并且该卡可能会被注销, 甚至可能会断电。它可能看似工作, 但可能正在引用已释放的存储。

原文:

You said : "I observed that if I unload and re-load the engine between different operations, i.e.:"

I don't think you should do that. You loose all the PKCS#11 objects, sessions, loaded keys etc. and the card may get logged out and may even get powered down. It may appear to work but may be referencing freed storage.

mtrojnar 2017-10-9
82

您对e4c87e5有什么意见或问题吗?其基本思想是将引擎提供给 libp11 的简约接口, 并为 libp11 提供实际的实现。

原文:

Do you have any comments or questions regarding e4c87e5? The basic idea is for the engine to only provide a minimalistic interface to libp11, and for libp11 to provide the actual implementation.

mouse07410 2017-10-9
83

您对e4c87e5有什么意见或问题吗?基本的想法是, 引擎只提供一个简约接口到 libp11, 并为 libp11 提供实际实现。

@mtrojnar一个评论-这个方法看起来不错。我喜欢新兴的建筑。

吨的问题-我不知道从哪里开始。现在, 工作代码将分布在 eng_front.c 上, 它对原始方法 ( bind_evp_pkey_methods()bind_fn() ) 进行挂钩, 并且 p11_rsa.c 在其中使用新方法 (如 pkcs11_pkey_rsa_sign() live)。

您认为哪些 "剩余代码" 应该转到 p11_pkey.c ?全部?只有添加到 eng_front.c 中的内容才能执行该方法挂钩? 我想了解有关这方面的更详细的指导。

此外, 有了这个新的 (而且是更好的) 体系结构, 我怀疑绑定过程应该改变吗?因此, bind_evp_pkey_methods() 将消失, 其功能将移动到 PKCS11_pkey_meths() ? 并且它将成为 PKCS11_pkey_meths() 作业来跟踪原始方法?

和 semi-related 的问题。它看起来像当前的实现 (我的分支 "rsa-oaep-orig", 这是 "rsa-oaep-准备", 直到我合并您的e4c87e5到它) 的方法保持钩的一个关键/上下文操作 (即, 使用公钥加密), 但在以下操作 (例如, 用私钥解密) 在同一引擎上, 但在不同的密钥上, 它们神秘地成为 "脱钩"。有什么明显的东西, 你在我们做了什么, 将导致这个问题?

原文:

Do you have any comments or questions regarding e4c87e5? The basic idea is for the engine to only provide a minimalistic interface to libp11, and for libp11 to provide the actual implementation.

@mtrojnar One comment - the approach looks good. I like the emerging architecture.

Ton of questions - I don't know where to start. Right now the working code is spread over eng_front.c where it does the hooking of the original methods (bind_evp_pkey_methods() and bind_fn()), and p11_rsa.c where the new methods like pkcs11_pkey_rsa_sign() live.

Which of those do you consider "remaining code" that should go to p11_pkey.c? All of it? Only the stuff that was added to eng_front.c to do the method hooking? I'd much appreciate more detailed guidance on that.

Also, with this new (and admittedly better) architecture, I suspect the binding process should change? So bind_evp_pkey_methods() would disappear and its functionality would move to PKCS11_pkey_meths()? And it would become PKCS11_pkey_meths() job to keep track of the original methods?

And semi-related question. It looks like with the current implementation (my branch "rsa-oaep-orig" that was "rsa-oaep-prep" until I merged your e4c87e5 into it) the methods stay hooked for one key/context operation (i.e., encrypt with a public key), but on the following operation (e.g., decrypt with a private key) on the same engine but on a different key they mysteriously become "unhooked". Is there something obvious to you in what we did that would cause this problem?

mouse07410 2017-10-9
84

你说: "我观察到, 如果我卸载和重新在不同的操作之间的引擎, 即:"

我认为你不应该那样做。您松开所有的 PKCS#11 对象、会话、加载的密钥等, 并且该卡可能会被注销, 甚至可能会断电。它可能看似工作, 但可能正在引用已释放的存储。

@dengert不幸的是, 你100% 是对的。不幸的是, 因为在这种情况下, 我不知道如何来, 在一个关键的引擎非常好的方法, 突然变得恢复到原来的, 当新的键加载在同一引擎。我不知道如何解决它。这将严重影响 OpenSSL-based 对 HSM 设备的编程访问。

附言哦, 谢谢-刚刚做了这个:

应该是

297 !(pmeth = EVP_PKEY_meth_new(EVP_PKEY_RSA, EVP_PKEY_FLAG_AUTOARGLEN))
原文:

You said : "I observed that if I unload and re-load the engine between different operations, i.e.:"

I don't think you should do that. You loose all the PKCS#11 objects, sessions, loaded keys etc. and the card may get logged out and may even get powered down. It may appear to work but may be referencing freed storage.

@dengert unfortunately you're 100% right. Unfortunately because in that case I've no clue how come that the methods that worked perfectly fine with the engine on one key suddenly become reverted to the original ones when the new key is loaded on the same engine. I don't know how to address it. And that would badly impact OpenSSL-based programmatic access to HSM devices.

P.S. Oh, and thank you - just did this:

should be

297 !(pmeth = EVP_PKEY_meth_new(EVP_PKEY_RSA, EVP_PKEY_FLAG_AUTOARGLEN))
mtrojnar 2017-10-9
85

你认为哪些 "剩余的代码" 应该去 p11_pkey?全部?

是的, 除了我已经放在那里的那段代码。

因此, bind_evp_pkey_methods () 将消失, 其功能将移动到 PKCS11_pkey_meths ()?

精确地 pkcs11_pkey_method_rsa ()

有什么明显的东西, 你在我们做了什么, 将导致这个问题?

坦率地说, 你现在的代码一团糟。我希望在我们清理的时候大部分的虫子都能修好。

我不 expecy 你做这份工作。我最终会做到的。 我只是现在没有太多的时间来做这个项目。

原文:

Which of those do you consider "remaining code" that should go to p11_pkey.c? All of it?

Yes, except for the piece of code I already put there.

So bind_evp_pkey_methods() would disappear and its functionality would move to PKCS11_pkey_meths()?

To pkcs11_pkey_method_rsa() to be precise.

Is there something obvious to you in what we did that would cause this problem?

Frankly, your current code is a mess. I expect most bugs to be fixed while we clean it up.

I don't expecy you to do this job. I will eventually do it. I just don't have too much time now to work on this project.

mouse07410 2017-10-9
86

坦率地说, 你现在的代码一团糟。

:-)我觉得你在这里太苛刻了

我希望在我们清理的时候大部分的虫子都能修好。

我不指望你做这份工作。我最终会做到的。我只是现在没有太多的时间来做这个项目。

理解.但它的不确定性的 "最终", 困扰我, 和力量尝试..。我宁愿早点吃 (当然, 这一切都取决于你的时间, 我们是在谈几周、几个月、几年吗?我当然可以等几个星期, 不确定几个月, 肯定不是年..。

原文:

Frankly, your current code is a mess.

:-) I do think you're being too harsh here.

I expect most bugs to be fixed while we clean it up.

I don't expect you to do this job. I will eventually do it. I just don't have too much time now to work on this project.

Understood. But it's the uncertainty of the "eventually" that bothers me, and forces to try... As I'd rather have it sooner than later (of course, it all depends on your time-frame - are we talking weeks, months, years? I certainly can wait weeks, not sure about months, definitely not year(s))...

dengert 2017-10-9
87

@mt您问: "您对e4c87e5有什么意见或问题吗?

evp_pkey 可以处理任何类型的密钥。meths 是由引擎支持的一堆方法。 现在, 我们只需要用 PSS 或 OAEP 填充处理 RSA。所以所有的代码都被放进了 p11_rsa。
所以可能会有 p11_pkey c 和 p11_pkey_rsa

当前 pkcs11_pkey_rsa 中的大部分代码是 PSS 和 OAEP 填充的特定于引擎的代码。它需要找到参数, 并转换为 PKCS#11 参数。

它也只处理 pss 或 OAEP, 并查看 PKCS#11 是否可以处理 pss 或 OAEP. n (它可以处理任何 RSA 填充, 并且我认为@mouse07410有这样做。如果它会回落, 让 OpenSSL 继续做填充和 OpenSSL 将最终调用旧的引擎代码做原始的 RSA 操作。这就是为什么 PIV 卡在没有这些代码的情况下工作, 但是 HSM 并没有因为它不支持 RSA RAW。evp_pkey 给引擎提供了使令牌处理填充的灵活性。

因此, 我不清楚你期望在 libp11, 它不可由用户, vs 什么代码只有引擎。 PKCS#11 的唯一实际区别是 PSS 和 OAEP 采取了一个机制参数。没有其他 RSA 机制。 这一代码的第一次削减了假设, 如果 PKCS#11 可以处理的操作, 然后让 OpenSSL 尝试处理它。 您是否希望它做得更多, 甚至处理 RSA RAW 类型卡的填充, 这样 "orig_pkey_rsa_" 例程就不会被调用?

原文:

@mt You asked: "Do you have any comments or questions regarding e4c87e5?"

The evp_pkey can handle any type of key. And the meths is a stack of methods supported by the engine. Right now we only need to handle RSA with PSS or OAEP padding. So all the code was put into p11_rsa.
So there could be a p11_pkey.c and p11_pkey_rsa.c

Much of the code in the current pkcs11_pkey_rsa is engine specific code for the PSS and OAEP padding. It needs to find the parameters and convert to PKCS#11 parameters.

It also only processes PSS or OAEP, and see if PKCS#11 can handle PSS or OAEP.n (It could handle any RSA padding, and I think @mouse07410 has it doing that. ) If it will fall back to letting OpenSSL continue doing the padding and OpenSSL will eventually call the older engine code to do RAW RSA operation. That is why the PIV cards worked without any of these code, but the HSM did not because it does not support RSA RAW. The evp_pkey gives the engine for flexibility to have the token handle the padding.

So it is not clear to me what you expect to be in libp11 that it accessable by the user, vs what code is there only for the engine. The only real differences in for PKCS#11 is that the PSS and OAEP take a mechanism parameter. No other RSA mechanism does. The firsts cuts of this code made the assumption that if PKCS#11 could handle the operation, then let OpenSSL try to handle it. Do you want it to do more, and even handle the padding for the RSA RAW types of cards so that the "orig_pkey_rsa_* routines are never called?

dengert 2017-10-9
88

@mtrojnar这里是另一个, 但从 libp11 的观点来看问题。

您一直暗示应该有一种方法可以将 PSS 和 OAEP 添加到 libp11 以供用户调用。这两个问题的主要问题是机制采取了一个参数。但 pkcs11_private_encrypt , pkcs11_private_decrypt 仅在 int padding 中传递, 并且没有方法传入参数。(OAEP 还需要一个 pkcs11_public_encryptpkcs11_mechanism基于 padding 对要使用的机制进行简单的假设。

主要的问题, 所有这些 mods 的地址是, 根据令牌的能力, 支持多个机制。如果它能支持 CKM_RSA_X_509, 所有的填充都可以在软件中完成。如果它只能支持 CKM_RSA_PKCS_PSS 和/或 CKM_RSA_PKCS_OAEP, 那么所有的填充都必须由标记来完成。

OpenSSL EVP_PKEY 代码传递给引擎, 使引擎能够选择是否可以在软件或硬件中进行填充。引擎代码可以根据令牌支持的内容在 pkcs11 _ * 例程中实现此选项。可以根据标记支持的机制在 pkcs11_mechanism 例程中进行选择。

你会考虑一个扩展版本的这些例程, 有一个额外的参数?

原始的 ' 证明概念 ' 代码做了选择前面然后, 如果标记支持 CKM_RSA_PKCS_PSS 并且/或者 CKM_RSA_PKCS_OAEP 它做了 PKCS # 电话。如果不是它让 OpenSSL 做填充是软件时, 结束了调用 pkcs11 _ * 例程与填充 == RSA_NO_PADDING 让令牌做 CKM_RSA_X_509。

然后, p11_evp 将组成 PSS 或 OAEP 参数, 并调用 pkcs11_private_decrypt_extended , pkcs11_private_encrypt_extendedpkcs11_public_encrypt_extended

pkcs11_private_decrypt, pkcs11_private_encryptpkcs11_public_encrypt 将只调用扩展版本的参数 = NULL。

原文:

@mtrojnar Here is another though, looking at the problem from the libp11 viewpoint.

You keep implying there should be a way to add PSS and OAEP to libp11 for users to call. The main issue with both of these is the mechanisms take a parameter. But pkcs11_private_encrypt, pkcs11_private_decrypt only pass in int padding and there is no way to pass in a parameter. (And OAEP also needs a pkcs11_public_encrypt.) pkcs11_mechanism makes a simple assumption based on padding as to the mechanism to be used.

The main issue that all these mods address is that depending on the token's ability to support several mechanisms. If it can support CKM_RSA_X_509 all the padding can be done in software. If it can only support CKM_RSA_PKCS_PSS and/or CKM_RSA_PKCS_OAEP, then all the padding must be done by the token.

The OpenSSL EVP_PKEY code passes to the engine the ability for the engine to choose if the padding can be done in software or hardware. The engine code could pass this choice to be implemented in the pkcs11_* routines based on what the token supports. The choice could be made in the pkcs11_mechanism routine based on the mechanisms supported by the token.

Would you consider an extended version of these routines, that have an additional parameter?

The original 'proof of concept" code made the choice up front then if the token supported CKM_RSA_PKCS_PSS and/or CKM_RSA_PKCS_OAEP it made the PKCS# calls. If not it let OpenSSL do the padding is software when ended up calling the pkcs11_* routines with padding==RSA_NO_PADDING to let the token do CKM_RSA_X_509.

The p11_evp.c would then make up the PSS or OAEP parameters, and call pkcs11_private_decrypt_extended, pkcs11_private_encrypt_extended or pkcs11_public_encrypt_extended.

The pkcs11_private_decrypt, pkcs11_private_encrypt and pkcs11_public_encrypt would just call the extended versions with a parameter=NULL.

mouse07410 2017-10-9
89

@mtrojnar我已将这些内容移到 src/p11_pkey.c (我的分支https://github.com/mouse07410/libp11/tree/rsa-oaep-prep)

问题仍然存在。它在单个调用时工作正常, 并且调用相应的 pkcs11_pkey_rsa_decrypt() 或这样的方法。但是, 当另一个键加载到同一引擎上时, 它无法继续执行自定义方法, 并且在 pkcs11_private_decrypt() in p11_rsa.c 中失败, 并使用 mechanism=3padding=3 (而不是 4)。

我不知道为什么成功的第一次加载的关键 (公共或私人) 与所有的方法被正确地映射, 随后加载的键找到方法 "未映射"。

以下是成功的 OpenSSL CLI 日志 (仅加载一次), 并带有调试跟踪:

$ ~/openssl-1.1/bin/openssl pkeyutl -engine pkcs11 -keyform engine -encrypt -in t27.txt -out t27.txt.oaep -pubin -inkey "pkcs11:token=YubiHSM;id=%04%02;type=public" -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_mgf1_md:sha256 -pkeyopt rsa_oaep_md:sha256
engine "pkcs11" set.
Enter PKCS#11 token PIN for YubiHSM:
p11_pkey.c:454 pkcs11_pkey_rsa_encrypt(): out=0x7f820c015c50 *outlen=512  in=0x7f820c0156a0 inlen=27
p11_pkey.c:483 pkcs11_pkey_rsa_encrypt(): orig_pkey_rsa_encrypt returned 1 (512)
$ ~/openssl-1.1/bin/openssl pkeyutl -engine pkcs11 -keyform engine -decrypt -in t27.txt.oaep -inkey "pkcs11:token=YubiHSM;id=%04%02;type=private" -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_mgf1_md:sha256 -pkeyopt rsa_oaep_md:sha256
engine "pkcs11" set.
Enter PKCS#11 token PIN for YubiHSM:
p11_pkey.c:297 pkcs11_pkey_rsa_decrypt() out=0x7fdca254f820  *outlen=512 in=0x7fdca254f570 inlen=512
p11_pkey.c:323 padding=4
RSA_OAEP
p11_pkey.c:337 hashAlg=SHA256 mgf=MGF1-SHA256 
p11_pkey.c:509 hashAlg=SHA256 mgf=MGF1-SHA256 
12345678901234567890123456
$ cat t27.txt
12345678901234567890123456
$ 

下面是对公钥编程加载的失败跟踪 (不重新创建上下文) 一堆加密, 然后加载私钥并失败, 因为它没有调用正确的 (自定义/映射) 方法, 而是转到原始的一个:

$ /tmp/OSSL-Tst3.dst/Users/ur20980/bin/OSSL-Tst3
Using YubiHSM device...

Generated random 256-bit AES key:
33 6a e5 8b 2a 8f 01 fd 6b 7a 8d d6 3d 22 f4 1f 
03 89 33 33 74 9a 8c fb b5 e9 e4 1a 98 54 e6 8e 

Enter PKCS#11 token PIN for YubiHSM:
wrap: created EVP_PKEY_CTX...
Symmetric key encrypted with RSA using RSA-OAEP padding (512 bytes):
2a 54 c4 66 b6 e5 df 68 26 d6 82 c5 d8 ca 4c 76 
7d ac 03 4d 95 16 0d c2 01 02 10 ee 5b 96 7c 92 
. . . . .
72 d5 3a 64 c4 72 05 07 72 6d 39 ae 6c e5 5b b0 

Generated random 256-bit AES key:
bf 7b b0 d1 f3 28 5f 01 34 e6 64 81 d0 e7 40 fa 
80 09 77 6e 06 89 14 e7 17 b1 10 42 31 ef 7c 65 

Symmetric key encrypted with RSA using RSA-OAEP padding (512 bytes):
16 6c fb 0a bc b2 cd 17 96 d5 2b d8 e2 fe a0 41
. . . . .
d8 42 70 9e 46 b4 f5 26 cc b5 bb 00 6d 19 9e 19 

unwrap: loaded privkey of size 512
unwrap: Created EVP_PKEY_CTX...
unwrap: allocating 512 bytes...
p11_rsa.c:162 pkcs11_private_decrypt: mech=3 padding=3
p11_rsa.c:183 pkcs11_private_decrypt: C_DecryptInit() returned 112
p11_rsa.c:193 pkcs11_private_decrypt: C_Decrypt() returned 112
p11_rsa.c:201 mechanism: 3 padding: 3
unwrap: failed to decrypt (rv=-1)
140735726228416:error:82079070:PKCS#11 module:pkcs11_private_decrypt:Mechanism invalid:p11_rsa.c:198:
Decryption failed! (rv=-1 olen=512)

OpenSSL crypto demo completed with errors!

它应该是显而易见的: 一些不应该设置的东西, 或者那些映射的持久性所需要的不设置的东西。我不知道该如何快速地发现这个问题, 但症状似乎很清楚。

原文:

@mtrojnar I've moved the stuff to src/p11_pkey.c (my branch https://github.com/mouse07410/libp11/tree/rsa-oaep-prep)

The problem persists. It works fine with single invocation, and the appropriate pkcs11_pkey_rsa_decrypt() or such methods are called. However when another key is loaded on the same engine, it fails to proceed to the custom methods, and fails in pkcs11_private_decrypt() in p11_rsa.c with mechanism=3, and padding=3 (instead of 4).

I have no idea why after successful first loading of the key (public or private) with all the methods being properly mapped, subsequent loading of the keys find methods "unmapped".

Here's successful log of OpenSSL CLI (only loads key once) with debugging trace:

$ ~/openssl-1.1/bin/openssl pkeyutl -engine pkcs11 -keyform engine -encrypt -in t27.txt -out t27.txt.oaep -pubin -inkey "pkcs11:token=YubiHSM;id=%04%02;type=public" -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_mgf1_md:sha256 -pkeyopt rsa_oaep_md:sha256
engine "pkcs11" set.
Enter PKCS#11 token PIN for YubiHSM:
p11_pkey.c:454 pkcs11_pkey_rsa_encrypt(): out=0x7f820c015c50 *outlen=512  in=0x7f820c0156a0 inlen=27
p11_pkey.c:483 pkcs11_pkey_rsa_encrypt(): orig_pkey_rsa_encrypt returned 1 (512)
$ ~/openssl-1.1/bin/openssl pkeyutl -engine pkcs11 -keyform engine -decrypt -in t27.txt.oaep -inkey "pkcs11:token=YubiHSM;id=%04%02;type=private" -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_mgf1_md:sha256 -pkeyopt rsa_oaep_md:sha256
engine "pkcs11" set.
Enter PKCS#11 token PIN for YubiHSM:
p11_pkey.c:297 pkcs11_pkey_rsa_decrypt() out=0x7fdca254f820  *outlen=512 in=0x7fdca254f570 inlen=512
p11_pkey.c:323 padding=4
RSA_OAEP
p11_pkey.c:337 hashAlg=SHA256 mgf=MGF1-SHA256 
p11_pkey.c:509 hashAlg=SHA256 mgf=MGF1-SHA256 
12345678901234567890123456
$ cat t27.txt
12345678901234567890123456
$ 

Here's the failing trace of programmatic loading of the public key and performing (without re-creating the context) a bunch of encryptions, then loading the private key and failing because instead of having the correct (customized/mapped) method invoked it goes to the original one:

$ /tmp/OSSL-Tst3.dst/Users/ur20980/bin/OSSL-Tst3
Using YubiHSM device...

Generated random 256-bit AES key:
33 6a e5 8b 2a 8f 01 fd 6b 7a 8d d6 3d 22 f4 1f 
03 89 33 33 74 9a 8c fb b5 e9 e4 1a 98 54 e6 8e 

Enter PKCS#11 token PIN for YubiHSM:
wrap: created EVP_PKEY_CTX...
Symmetric key encrypted with RSA using RSA-OAEP padding (512 bytes):
2a 54 c4 66 b6 e5 df 68 26 d6 82 c5 d8 ca 4c 76 
7d ac 03 4d 95 16 0d c2 01 02 10 ee 5b 96 7c 92 
. . . . .
72 d5 3a 64 c4 72 05 07 72 6d 39 ae 6c e5 5b b0 

Generated random 256-bit AES key:
bf 7b b0 d1 f3 28 5f 01 34 e6 64 81 d0 e7 40 fa 
80 09 77 6e 06 89 14 e7 17 b1 10 42 31 ef 7c 65 

Symmetric key encrypted with RSA using RSA-OAEP padding (512 bytes):
16 6c fb 0a bc b2 cd 17 96 d5 2b d8 e2 fe a0 41
. . . . .
d8 42 70 9e 46 b4 f5 26 cc b5 bb 00 6d 19 9e 19 

unwrap: loaded privkey of size 512
unwrap: Created EVP_PKEY_CTX...
unwrap: allocating 512 bytes...
p11_rsa.c:162 pkcs11_private_decrypt: mech=3 padding=3
p11_rsa.c:183 pkcs11_private_decrypt: C_DecryptInit() returned 112
p11_rsa.c:193 pkcs11_private_decrypt: C_Decrypt() returned 112
p11_rsa.c:201 mechanism: 3 padding: 3
unwrap: failed to decrypt (rv=-1)
140735726228416:error:82079070:PKCS#11 module:pkcs11_private_decrypt:Mechanism invalid:p11_rsa.c:198:
Decryption failed! (rv=-1 olen=512)

OpenSSL crypto demo completed with errors!

It should be something obvious: something set that shouldn't be set, or something not set that was required for persistence of those mappings. I don't know enough to find that problem reasonably fast, but the symptoms seem very clear.

mouse07410 2017-10-9
90

@dengert坦率地说, 我不喜欢这样:

   pmeth = EVP_PKEY_meth_new(EVP_PKEY_RSA, EVP_PKEY_FLAG_AUTOARGLEN)

因为它意味着调用方被告知分配最大缓冲区 (在这种情况下为4096位的 RSA 密钥512字节), 而真正需要的是27字节。

我的代码已经正确地处理了这个。您仍然认为我们需要 AUTOARGLEN 吗?或者我是否应该将它返回到 0, 因为 ...decrypt()...encrypt() 都做了正确的事情?

原文:

@dengert frankly I don't like this:

   pmeth = EVP_PKEY_meth_new(EVP_PKEY_RSA, EVP_PKEY_FLAG_AUTOARGLEN)

because it means the caller is told to allocate the maximum buffer (in this case of 4096-bit RSA keys 512 bytes), while what's really needed is 27 bytes.

My code already handles this correctly. Do you still think we want AUTOARGLEN? Or should I just return it to 0, as both ...decrypt() and ...encrypt() do the right thing?

dengert 2017-10-9
91

@mouse07410 问题可能是由 engine_unlocked_finish 造成的, 因为我们可能会错过一个调用
ENGINE_up_ref (或任何) 的每 pkey 我们有。

EVP_PKEY_free 呼叫 EVP_PKEY_free_it 呼叫 ENGINE_finish (x > 引擎);这会递减一些 ref 计数。

使用调试器, 查看是否设置了 pkey > 引擎。

这可能也是未修改的代码中的一个问题。

原文:

@mouse07410 The problem maybe caused by engine_unlocked_finish, as we may be missing a call to
ENGINE_up_ref (or whatever) for every pkey we have.

EVP_PKEY_free calls EVP_PKEY_free_it that calls ENGINE_finish(x->engine); This decrements some ref count.

With a debugger, look to see if pkey->engine is set.

This could be a problem in unmodified code too.

dengert 2017-10-9
92

问题是, 所有方法入口点都有一个 EVP_PKEY_FLAG_AUTOARGLEN 标志。 我们只替换2或3。 所有其他的都是从默认设置中复制的, 而这些缺省值将被设定。您将需要替换所有这些。 (为什么 EVP_PKEY_FLAG_AUTOARGLEN 不是默认值, 我不知道。

使用推荐的标志将允许您删除大量的本地代码。其他填充方法或 RSA RAW 将期望512字节缓冲区。注意, 人页说 "最大", 所以 OpenSSL 没有问题, 浪费一些存储在他们的默认方法。

在调用任何方法例程之前, 检查出 = = null, 因此您的例程不应显示为 null。

原文:

The problem, is there is one EVP_PKEY_FLAG_AUTOARGLEN flag for all the method entry points. We only replace 2 or 3 of them. All the others are copied from the defaults that expect the flag to have been set. You will need to replace all of them. (Why EVP_PKEY_FLAG_AUTOARGLEN was not the default, I don't know.)

Using the recommended flag will allow you to remove a lot of local code. Other padding methods or RSA RAW will expect 512 byte buffer. Note the man pages say "maximum" so OpenSSL has no problem with wasting some storage in their the default methods.

And the check for out==NULL is done before any of the method routines are called, so your routines should never see out==NULL.

mouse07410 2017-10-9
93

@mouse07410问题可能是由 engine_unlocked_finish 引起的, 因为我们可能缺少对每一个 pkey 的调用. EVP_PKEY_free 调用 EVP_PKEY_free_it 调用 ENGINE_finish(x->engine); 这会递减一些 ref 计数。

我听到你 (虽然我没有足够深的理解, 完全遵循)。但是引擎本身似乎是工作的, 它仍然接收令牌上的键的命令。它只是丢失了我们创建的方法映射, 因此操作会被误导, 但我认为它们留在引擎中。

使用调试器, 查看是否设置了 pkey->engine

将尝试检查。

这可能也是未修改的代码中的一个问题。

可能.我不知道, 因为我没有什么可比的。未修改的和修改过的代码似乎都可以使用 PIV 令牌, 包括编程访问。未修改的代码从未与 HSM 设备一起使用, 修改过的程序在加载另一个键后丢失了方法映射...:-(

使用推荐的标志将允许您删除大量的本地代码。

当然, 但本地代码并不困扰我, 它充当了一个 "后卫", 对任何可能的问题与一个愚蠢的调用与一个空缓冲区。"皮带和吊带", 如果你愿意。每个方法只有几行代码 (大约15行代码总数)..。我不知道。。。

其他填充方法或 RSA RAW 将期望512字节缓冲区。

这是一个重要的论据。也许推翻我所说的大部分与 AUTOARGLEN。

注意, 人页说 "最大", 所以 OpenSSL 没有问题, 浪费一些存储在他们的默认方法。

好吧, 我们不需要遵循所有的 mis-features 的 OpenSSL。;-)
不过, 我明白你的意思。

所以, 你说 "保持 AUTOARGLEN, 并摆脱本地代码的空缓冲区"?我有点不情愿摆脱这些代码 (让我们给它一些时间), 但没有问题, 保持 AUTOARGLEN。 谢谢!

原文:

@mouse07410 The problem maybe caused by engine_unlocked_finish, as we may be missing a call to ENGINE_up_ref (or whatever) for every pkey we have. EVP_PKEY_free calls EVP_PKEY_free_it that calls ENGINE_finish(x->engine); This decrements some ref count.

I hear you (though I don't have understanding deep enough to follow completely). But the engine per se seems to work, and it still receives commands for the keys on the token. It just loses the method mappings that we created, so the operations get misdirected - but I think they stay within the engine.

With a debugger, look to see if pkey->engine is set.

Will try to check.

This could be a problem in unmodified code too.

Possibly. I don't know, as I don't have anything to compare to. Both the unmodified and the modified code seem to work OK with a PIV token, including programmatic access. The unmodified code never worked with the HSM device, and the modified one loses the method mappings after the load of another key... :-(

Using the recommended flag will allow you to remove a lot of local code.

Sure, but that local code doesn't bother me - and it serves as a "guard" against any possible problem with a silly call with a NULL buffer. "Belt and suspenders", if you will. And it's only a few lines of code per method (so approximately 15 lines of code total)... I don't know...

Other padding methods or RSA RAW will expect 512 byte buffer.

That's an important argument. Perhaps overruling most of what I said above related to AUTOARGLEN.

Note the man pages say "maximum" so OpenSSL has no problem with wasting some storage in their the default methods.

Well, we don't have to follow all the mis-features of OpenSSL. ;-)
Still, I see your point.

So you say "keep AUTOARGLEN, and get rid of the local code for NULL buffer"? I'm somewhat reluctant to get rid of that code (let's give it some time), but have no problem keeping AUTOARGLEN in. Thanks!

mouse07410 2017-10-9
94

@dengert我已经做了一些跟踪与调试器, 我不能说我完全理解的结果。

  1. e = load_engine("pkcs11");引擎负载正常, 它有 rsa_meth 组名为 "libp11 RSA 方法", 它包含 rsa_pub_enc() , rsa_pub_dec() 位于 rsa_ossl.c 从 libcrypto dylib, 以及 rsa_priv_enc()rsa_priv_dec() 位于 p11_rsa.c pkcs11. dylib。它也有 pkey_meths 指针 pkey_meths ENGINE_PKEY_METHS_PTR (pkcs11.dylib PKCS11_pkey_meths 在 p11_pkey. c: 123) 0x0000000100b4c4e0 '。

  2. 继续进行 OAEP 加密。由于没有对令牌进行加密, 所以它的工作原理与几乎所有内容无关。

  3. 继续进行 OAEP 解密。正在加载私钥: privkey = ENGINE_load_private_key(e, KeyManPrivKey, NULL, &cb_data); 和您怀疑的一样 privkey->engine = NULL我, 它为 PIV 标记工作, 因为它们需要 OpenSSL 软件来进行填充, 并且引擎被注册为 RSA 操作的 "默认"。但是, 当更多的是需要从发动机-像 HSM-它失败.

我们现在怎么办?

更新(与以上所给的细节相比)

  • privkey->engine == NULL
  • privkey->pkey->rsa->meth点在 "旧" 函数, 如 rsa_priv_dec() 中定义的 p11_rsa.crsa_pub_enc() 在 OpenSSL 中定义的rsa_ossl.c
  • privkey->pkey->rsa->engine == NULL

为引擎本身:

  • e->rsa_meth点在 "老" 作用的集合 (如上所述)
  • e->pkey_meths:pkey_meths ENGINE_PKEY_METHS_PTR (pkcs11.dylibPKCS11_pkey_meths at p11_pkey.c:123) 0x0000000100b4c4e0
原文:

@dengert I've did some tracing with the debugger, and I can't say I fully comprehend the results.

  1. e = load_engine("pkcs11"); engine loads fine, it has rsa_meth group named "libp11 RSA method" that contains rsa_pub_enc(), rsa_pub_dec() located in rsa_ossl.c from libcrypto.dylib, and rsa_priv_enc() and rsa_priv_dec() located in p11_rsa.c of pkcs11.dylib. It also has pkey_meths pointer pkey_meths ENGINE_PKEY_METHS_PTR (pkcs11.dylibPKCS11_pkey_meths at p11_pkey.c:123) 0x0000000100b4c4e0`.

  2. Proceeding with OAEP encryption. Since encryption is not done on the token anyway, it works regardless of almost everything.

  3. Proceeding to OAEP decryption. Loading private key: privkey = ENGINE_load_private_key(e, KeyManPrivKey, NULL, &cb_data); and as you suspected, privkey->engine = NULL. IMHO, it worked for PIV tokens, because they require OpenSSL software to do the padding, and the engine is registered as "default" for RSA operations. But when more is required from the engine - like with HSM - it fails.

What do we do now?

Update (with more details than given above)

  • privkey->engine == NULL
  • privkey->pkey->rsa->meth points at the "old" functions like rsa_priv_dec() defined in p11_rsa.c and rsa_pub_enc() defined in OpenSSL in rsa_ossl.c
  • privkey->pkey->rsa->engine == NULL

For the engine itself:

  • e->rsa_meth points at the set of the "old" functions (as above)
  • e->pkey_meths: pkey_meths ENGINE_PKEY_METHS_PTR (pkcs11.dylibPKCS11_pkey_meths at p11_pkey.c:123) 0x0000000100b4c4e0
dengert 2017-10-9
95

我不清楚为什么第一把钥匙会起作用, 而不是其他的。这可能是因为引擎上的引用计数。我认为这是你的申请失败。您可以设置多个断点以查看
可能发生的事情例如, 设置断点的 pkcs11_pkey_rsa _ * 例程以及默认的 pkey_rsa_ * 例程, 以查看是否和当每个被调用。当你休息时, 看看栈迹。

也打破了 ENGINE_init, ENGINE_get_pkey_meth_engine, EVP_PKEY_up_ref, ENGINE_get_pkey_meth
和 int_ctx_new 一步通过这最后一个, 看看它做什么。看看 ENGINE_get_pkey_meth_engine 是否用引擎来称呼, 从哪里来, 什么是 id。

@mtrojnar@mouse07410 ctx_new创建 ENGINE_CTX , 但它确实会保存指向该引擎的指针 ENGINE_CTX 。 您是否发现将 ctx_new() 更改为 ctx_new(ENGINE *e)
然后添加 ctx->engine = e; 这可能需要在将来的代码中获取引擎的地址。

使用 EVP_PKEY, 修改后的方法将被绑定到引擎, 只有在 EVP_PKEY
(evp_pkey_st/密码/包含/内部/evp_int. h。有一个引擎。

但我不知道如何从 ctx_load_key, ctx_load_pubkey, ctx_load_privkey。

@mouse07410注意在 OpenSSL pkeyutl c, init_ctx () 他们使用 impl。
然后他们做:

385         int kdfnid = OBJ_sn2nid(kdfalg);
386         if (kdfnid == NID_undef)
387             goto end;
388         ctx = EVP_PKEY_CTX_new_id(kdfnid, impl);
389     } else {
390         if (pkey == NULL)
391             goto end;
392         *pkeysize = EVP_PKEY_size(pkey);
393         ctx = EVP_PKEY_CTX_new(pkey, impl);
394         EVP_PKEY_free(pkey);
395     }

这是不明显的为什么他们做一个 EVP_PKEY_free, 其他然后它被复制的 EVP_PKEY_CTX_new。

原文:

It is not clear to me why the first key would work, but not the rest. This could be because of a reference count on the engine. I assume this is your application that is failing. You can set many breakpoints to see
what might be going on. For example set breakpoints for the pkcs11_pkey_rsa_* routines as well as the default pkey_rsa_* routines to see if and when each gets called. Look at the stack trace when you get a break.

Also break on ENGINE_init, ENGINE_get_pkey_meth_engine, EVP_PKEY_up_ref, ENGINE_get_pkey_meth
and int_ctx_new step through this last one and see what it does. See if ENGINE_get_pkey_meth_engine is called with an engine, and from where, and what is the id.

@mtrojnar @mouse07410 ctx_new creates the ENGINE_CTX, but it does does save a pointer to the engine in ENGINE_CTX. Do you see any problem with changing ctx_new() to ctx_new(ENGINE *e)
then adding ctx->engine = e; This might be needed to get the address of the engine in some future code.

With an EVP_PKEY, the modified methods are tied to the engine and will only be found if the EVP_PKEY
(evp_pkey_st in ./crypto/include/internal/evp_int.h.) has an engine.

But I don't see how to set it from ctx_load_key, ctx_load_pubkey, ctx_load_privkey.

@mouse07410 Note in the OpenSSL pkeyutl.c, init_ctx() they use the impl.
They then do:

385         int kdfnid = OBJ_sn2nid(kdfalg);
386         if (kdfnid == NID_undef)
387             goto end;
388         ctx = EVP_PKEY_CTX_new_id(kdfnid, impl);
389     } else {
390         if (pkey == NULL)
391             goto end;
392         *pkeysize = EVP_PKEY_size(pkey);
393         ctx = EVP_PKEY_CTX_new(pkey, impl);
394         EVP_PKEY_free(pkey);
395     }

It is not obvious why they do a EVP_PKEY_free, other then it was copied by the EVP_PKEY_CTX_new.

mouse07410 2017-10-9
96

@mouse07410注意在 OpenSSL pkeyutl c, init_ctx () 他们使用 impl。

是的。但在我们的情况下, 它是否设置为 "引擎" 或 "NULL" 还不清楚。而且, 因为当我使用 "pkeyutl" 我做指定 "-engine_impl" 参数-我怀疑什么是传递到 EVP_PKEY_CTX_new()NULL

原文:

@mouse07410 Note in the OpenSSL pkeyutl.c, init_ctx() they use the impl.

Yes. But it is unclear if it's set to "engine" or to "NULL" in our case. And since when I use "pkeyutl" I do not specify "-engine_impl" parameter - I suspect what's passed to EVP_PKEY_CTX_new() is NULL.

mtrojnar 2017-10-9
97

@dengert我认为我们不应该把我们的参考或指针的引擎。无论如何, 让我们尝试诊断问题之前, 我们提出一个修复。

接下来的几天我都在休假, 没有真正的键盘。我回来时会调查的

原文:

@dengert I don't think we should keep our reference or pointer to the engine. Anyway, let's try to diagnose the issue before we propose a fix.

I'm on my vacation for the next few days with no access to a real keyboard. I will look into it when I return.

mtrojnar 2017-10-9
98

load_privkey()in eng_front.c 不应该设置返回的 evp_pkey_st 对象的 engine 属性吗?

原文:

Shouldn't load_privkey() in eng_front.c set the engine property of the returned evp_pkey_st object?

mouse07410 2017-10-9
99

load_privkey()in eng_front.c 不应该设置返回的 evp_pkey_st 对象的引擎属性吗?

我怎么会知道?;-)

我认为这是你的申请失败。

原来, 当我做了一些修改 (见下面的细节), 我的应用程序开始正常工作。

当前状态
在处理 PIV 设备 (或支持原始 RSA 的设备) 时, 无论您是用引擎创建上下文, 还是不使用发动机, 即 ctx = EVP_PKEY_CTX_new(pkey, engine);
ctx = EVP_PKEY_CTX_new(pkey, NULL);工作同样精细。

当处理这个新的 (对我) 不做原始 RSA 的 HSM 设备时, 在 ctx = EVP_PKEY_CTX_new(pkey, engine); 中提供引擎成为必要。这 (以及一些小的代码在 p11_pkey.c 中的抛光) 足以使加密和解密正常工作。

有了签名, 我发现我的不满, 旧的方式 (以前的罚款) 不再工作了。例如, 以下操作失败:

            EVP_PKEY_CTX *ctx = NULL;

            privkey = ENGINE_load_private_key(e, SignPrivKey, NULL, &cb_data);
            md = EVP_sha256();
            md_ctx = EVP_MD_CTX_create();
            rv = EVP_DigestSignInit(md_ctx, &ctx, md, e, privkey);
            rv = EVP_PKEY_CTX_set_rsa_padding(ctx, padding);
            EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, md);
            rv =  EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, -2);
            rv = EVP_DigestSignUpdate(md_ctx, in, inlen);
            olen = 0;
            rv = EVP_DigestSignFinal(md_ctx, NULL, &olen);
            *out = OPENSSL_malloc(&olen);
            rv = EVP_DigestSignFinal(md_ctx, *out, &olen);

我把上面的内容换成:

    md = EVP_sha256();
    ctx = EVP_PKEY_CTX_new(privkey, e);
    rv = EVP_PKEY_sign_init(ctx);
    rv = EVP_PKEY_CTX_set_rsa_padding(ctx, padding);
    EVP_PKEY_CTX_set_signature_md(ctx, md);
    EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, md);
    EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, -2);
    rv = EVP_PKEY_sign(ctx, NULL, &olen, in, inlen);
    *out = OPENSSL_malloc(olen);
    rv = EVP_PKEY_sign(ctx, *out, &olen, in, inlen);

这意味着现在我只能对长度等于摘要大小的数据进行签名 (或者自己 pre-hash)。

其他一切似乎都很正常, 无论是 OpenSSL CLI 还是我的代码。

更新
现在我想 backport 这个代码 OpenSSL-1.0.2。问题: 某些方法丢失。特别是:

  • EVP_PKEY_meth_get_sign
  • EVP_PKEY_meth_get_decrypt
  • EVP_PKEY_meth_get_encrypt

它们将在结构 evp_pkey_method_st 中返回的方法。该结构不透明 (在二进制 OpenSSL-1.0.2 安装中不可用), 并且仅在 crypto/include/internal/evp_int.h 中存在。

@mtrojnar如果将该文件包含在中 libp11 , 或者将结构定义从它中翻录并添加到或这样的内容中, 是否可以 src/p11_pkey.h ?如果没有这种新的能力, 我想 backported 1.0.2。

原文:

Shouldn't load_privkey() in eng_front.c set the engine property of the returned evp_pkey_st object?

How would I know? ;-)

I assume this is your application that is failing.

Turns out that when I made a few modifications (see below for details), my app started working correctly.

Current status
When dealing with a PIV device (or a device that supports raw RSA), it doesn't matter whether you create the context with or without engine, i.e., both ctx = EVP_PKEY_CTX_new(pkey, engine); and
ctx = EVP_PKEY_CTX_new(pkey, NULL); worked equally fine.

When dealing with this new (to me) HSM device that does not do raw RSA at all, providing the engine in ctx = EVP_PKEY_CTX_new(pkey, engine); became a necessity. This (and some minor polishing of the code in p11_pkey.c) was sufficient to get encryption and decryption working OK.

With the signature, I found to my displeasure that the old way (that was fine before) doesn't work any more. I.e., the following fails:

            EVP_PKEY_CTX *ctx = NULL;

            privkey = ENGINE_load_private_key(e, SignPrivKey, NULL, &cb_data);
            md = EVP_sha256();
            md_ctx = EVP_MD_CTX_create();
            rv = EVP_DigestSignInit(md_ctx, &ctx, md, e, privkey);
            rv = EVP_PKEY_CTX_set_rsa_padding(ctx, padding);
            EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, md);
            rv =  EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, -2);
            rv = EVP_DigestSignUpdate(md_ctx, in, inlen);
            olen = 0;
            rv = EVP_DigestSignFinal(md_ctx, NULL, &olen);
            *out = OPENSSL_malloc(&olen);
            rv = EVP_DigestSignFinal(md_ctx, *out, &olen);

I had replace the above with:

    md = EVP_sha256();
    ctx = EVP_PKEY_CTX_new(privkey, e);
    rv = EVP_PKEY_sign_init(ctx);
    rv = EVP_PKEY_CTX_set_rsa_padding(ctx, padding);
    EVP_PKEY_CTX_set_signature_md(ctx, md);
    EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, md);
    EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, -2);
    rv = EVP_PKEY_sign(ctx, NULL, &olen, in, inlen);
    *out = OPENSSL_malloc(olen);
    rv = EVP_PKEY_sign(ctx, *out, &olen, in, inlen);

which means that now I can only sign data equal in length to the digest size (or pre-hash it myself).

Everything else appears to work fine, both OpenSSL CLI and my code.

Update
Now I'd like to backport this code to OpenSSL-1.0.2. Problem: some methods are missing. In particular:

  • EVP_PKEY_meth_get_sign
  • EVP_PKEY_meth_get_decrypt
  • EVP_PKEY_meth_get_encrypt

The methods they would return live in the structure evp_pkey_method_st. That structure is opaque (not available in a binary OpenSSL-1.0.2 installation), and only lives in crypto/include/internal/evp_int.h.

@mtrojnar are you OK if I include that file into libp11, or rip the structure definition from it and add to src/p11_pkey.h or such? Without that this new capability cannot be backported to 1.0.2, I think.

返回
发表文章
mouse07410
文章数
4
评论数
67
注册排名
60712