summaryrefslogtreecommitdiff
path: root/sk-usbhid.c
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2020-04-28 04:02:29 +0000
committerDamien Miller <djm@mindrot.org>2020-05-01 13:13:29 +1000
commit59d2de956ed29aa5565ed5e5947a7abdb27ac013 (patch)
tree983def72c15590c50a0319c8048b9a7d56961edf /sk-usbhid.c
parentc9d10dbc0ccfb1c7568bbb784f7aeb7a0b5ded12 (diff)
downloadopenssh-git-59d2de956ed29aa5565ed5e5947a7abdb27ac013.tar.gz
upstream: when signing a challenge using a FIDO toke, perform the
hashing in the middleware layer rather than in ssh code. This allows middlewares that call APIs that perform the hashing implicitly (including Microsoft's AFAIK). ok markus@ OpenBSD-Commit-ID: c9fc8630aba26c75d5016884932f08a5a237f37d
Diffstat (limited to 'sk-usbhid.c')
-rw-r--r--sk-usbhid.c35
1 files changed, 32 insertions, 3 deletions
diff --git a/sk-usbhid.c b/sk-usbhid.c
index ad83054a..db6c0057 100644
--- a/sk-usbhid.c
+++ b/sk-usbhid.c
@@ -24,6 +24,7 @@
#include <stdio.h>
#include <stddef.h>
#include <stdarg.h>
+#include <sha2.h>
#ifdef WITH_OPENSSL
#include <openssl/opensslv.h>
@@ -31,6 +32,7 @@
#include <openssl/bn.h>
#include <openssl/ec.h>
#include <openssl/ecdsa.h>
+#include <openssl/evp.h>
#endif /* WITH_OPENSSL */
#include <fido.h>
@@ -710,8 +712,28 @@ check_sign_load_resident_options(struct sk_option **options, char **devicep)
return 0;
}
+/* Calculate SHA256(m) */
+static int
+sha256_mem(const void *m, size_t mlen, u_char *d, size_t dlen)
+{
+#ifdef WITH_OPENSSL
+ u_int mdlen;
+#endif
+
+ if (dlen != 32)
+ return -1;
+#ifdef WITH_OPENSSL
+ mdlen = dlen;
+ if (!EVP_Digest(m, mlen, d, &mdlen, EVP_sha256(), NULL))
+ return -1;
+#else
+ SHA256Data(m, mlen, d);
+#endif
+ return 0;
+}
+
int
-sk_sign(uint32_t alg, const uint8_t *message, size_t message_len,
+sk_sign(uint32_t alg, const uint8_t *data, size_t datalen,
const char *application,
const uint8_t *key_handle, size_t key_handle_len,
uint8_t flags, const char *pin, struct sk_option **options,
@@ -721,6 +743,7 @@ sk_sign(uint32_t alg, const uint8_t *message, size_t message_len,
char *device = NULL;
fido_dev_t *dev = NULL;
struct sk_sign_response *response = NULL;
+ uint8_t message[32];
int ret = SSH_SK_ERR_GENERAL;
int r;
@@ -735,7 +758,12 @@ sk_sign(uint32_t alg, const uint8_t *message, size_t message_len,
*sign_response = NULL;
if (check_sign_load_resident_options(options, &device) != 0)
goto out; /* error already logged */
- if ((dev = find_device(device, message, message_len,
+ /* hash data to be signed before it goes to the security key */
+ if ((r = sha256_mem(data, datalen, message, sizeof(message))) != 0) {
+ skdebug(__func__, "hash message failed");
+ goto out;
+ }
+ if ((dev = find_device(device, message, sizeof(message),
application, key_handle, key_handle_len)) == NULL) {
skdebug(__func__, "couldn't find device for key handle");
goto out;
@@ -745,7 +773,7 @@ sk_sign(uint32_t alg, const uint8_t *message, size_t message_len,
goto out;
}
if ((r = fido_assert_set_clientdata_hash(assert, message,
- message_len)) != FIDO_OK) {
+ sizeof(message))) != FIDO_OK) {
skdebug(__func__, "fido_assert_set_clientdata_hash: %s",
fido_strerr(r));
goto out;
@@ -783,6 +811,7 @@ sk_sign(uint32_t alg, const uint8_t *message, size_t message_len,
response = NULL;
ret = 0;
out:
+ explicit_bzero(message, sizeof(message));
free(device);
if (response != NULL) {
free(response->sig_r);