eddsa_sig.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. /*
  2. * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
  3. *
  4. * Licensed under the Apache License 2.0 (the "License"). You may not use
  5. * this file except in compliance with the License. You can obtain a copy
  6. * in the file LICENSE in the source distribution or at
  7. * https://www.openssl.org/source/license.html
  8. */
  9. #include <openssl/crypto.h>
  10. #include <openssl/core_dispatch.h>
  11. #include <openssl/core_names.h>
  12. #include <openssl/err.h>
  13. #include <openssl/params.h>
  14. #include <openssl/evp.h>
  15. #include <openssl/proverr.h>
  16. #include "internal/nelem.h"
  17. #include "internal/sizes.h"
  18. #include "prov/providercommon.h"
  19. #include "prov/implementations.h"
  20. #include "prov/provider_ctx.h"
  21. #include "prov/der_ecx.h"
  22. #include "crypto/ecx.h"
  23. #ifdef S390X_EC_ASM
  24. # include "s390x_arch.h"
  25. # define S390X_CAN_SIGN(edtype) \
  26. ((OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_##edtype)) \
  27. && (OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_##edtype)) \
  28. && (OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_##edtype)))
  29. static int s390x_ed25519_digestsign(const ECX_KEY *edkey, unsigned char *sig,
  30. const unsigned char *tbs, size_t tbslen);
  31. static int s390x_ed448_digestsign(const ECX_KEY *edkey, unsigned char *sig,
  32. const unsigned char *tbs, size_t tbslen);
  33. static int s390x_ed25519_digestverify(const ECX_KEY *edkey,
  34. const unsigned char *sig,
  35. const unsigned char *tbs, size_t tbslen);
  36. static int s390x_ed448_digestverify(const ECX_KEY *edkey,
  37. const unsigned char *sig,
  38. const unsigned char *tbs, size_t tbslen);
  39. #endif /* S390X_EC_ASM */
  40. static OSSL_FUNC_signature_newctx_fn eddsa_newctx;
  41. static OSSL_FUNC_signature_digest_sign_init_fn eddsa_digest_signverify_init;
  42. static OSSL_FUNC_signature_digest_sign_fn ed25519_digest_sign;
  43. static OSSL_FUNC_signature_digest_sign_fn ed448_digest_sign;
  44. static OSSL_FUNC_signature_digest_verify_fn ed25519_digest_verify;
  45. static OSSL_FUNC_signature_digest_verify_fn ed448_digest_verify;
  46. static OSSL_FUNC_signature_freectx_fn eddsa_freectx;
  47. static OSSL_FUNC_signature_dupctx_fn eddsa_dupctx;
  48. static OSSL_FUNC_signature_get_ctx_params_fn eddsa_get_ctx_params;
  49. static OSSL_FUNC_signature_gettable_ctx_params_fn eddsa_gettable_ctx_params;
  50. typedef struct {
  51. OSSL_LIB_CTX *libctx;
  52. ECX_KEY *key;
  53. /* The Algorithm Identifier of the signature algorithm */
  54. unsigned char aid_buf[OSSL_MAX_ALGORITHM_ID_SIZE];
  55. unsigned char *aid;
  56. size_t aid_len;
  57. } PROV_EDDSA_CTX;
  58. static void *eddsa_newctx(void *provctx, const char *propq_unused)
  59. {
  60. PROV_EDDSA_CTX *peddsactx;
  61. if (!ossl_prov_is_running())
  62. return NULL;
  63. peddsactx = OPENSSL_zalloc(sizeof(PROV_EDDSA_CTX));
  64. if (peddsactx == NULL)
  65. return NULL;
  66. peddsactx->libctx = PROV_LIBCTX_OF(provctx);
  67. return peddsactx;
  68. }
  69. static int eddsa_digest_signverify_init(void *vpeddsactx, const char *mdname,
  70. void *vedkey,
  71. ossl_unused const OSSL_PARAM params[])
  72. {
  73. PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
  74. ECX_KEY *edkey = (ECX_KEY *)vedkey;
  75. WPACKET pkt;
  76. int ret;
  77. if (!ossl_prov_is_running())
  78. return 0;
  79. if (mdname != NULL && mdname[0] != '\0') {
  80. ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST);
  81. return 0;
  82. }
  83. if (edkey == NULL) {
  84. if (peddsactx->key != NULL)
  85. /* there is nothing to do on reinit */
  86. return 1;
  87. ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET);
  88. return 0;
  89. }
  90. if (!ossl_ecx_key_up_ref(edkey)) {
  91. ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
  92. return 0;
  93. }
  94. /*
  95. * We do not care about DER writing errors.
  96. * All it really means is that for some reason, there's no
  97. * AlgorithmIdentifier to be had, but the operation itself is
  98. * still valid, just as long as it's not used to construct
  99. * anything that needs an AlgorithmIdentifier.
  100. */
  101. peddsactx->aid_len = 0;
  102. ret = WPACKET_init_der(&pkt, peddsactx->aid_buf, sizeof(peddsactx->aid_buf));
  103. switch (edkey->type) {
  104. case ECX_KEY_TYPE_ED25519:
  105. ret = ret && ossl_DER_w_algorithmIdentifier_ED25519(&pkt, -1, edkey);
  106. break;
  107. case ECX_KEY_TYPE_ED448:
  108. ret = ret && ossl_DER_w_algorithmIdentifier_ED448(&pkt, -1, edkey);
  109. break;
  110. default:
  111. /* Should never happen */
  112. ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
  113. ossl_ecx_key_free(edkey);
  114. return 0;
  115. }
  116. if (ret && WPACKET_finish(&pkt)) {
  117. WPACKET_get_total_written(&pkt, &peddsactx->aid_len);
  118. peddsactx->aid = WPACKET_get_curr(&pkt);
  119. }
  120. WPACKET_cleanup(&pkt);
  121. peddsactx->key = edkey;
  122. return 1;
  123. }
  124. int ed25519_digest_sign(void *vpeddsactx, unsigned char *sigret,
  125. size_t *siglen, size_t sigsize,
  126. const unsigned char *tbs, size_t tbslen)
  127. {
  128. PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
  129. const ECX_KEY *edkey = peddsactx->key;
  130. if (!ossl_prov_is_running())
  131. return 0;
  132. if (sigret == NULL) {
  133. *siglen = ED25519_SIGSIZE;
  134. return 1;
  135. }
  136. if (sigsize < ED25519_SIGSIZE) {
  137. ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
  138. return 0;
  139. }
  140. if (edkey->privkey == NULL) {
  141. ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY);
  142. return 0;
  143. }
  144. #ifdef S390X_EC_ASM
  145. if (S390X_CAN_SIGN(ED25519)) {
  146. if (s390x_ed25519_digestsign(edkey, sigret, tbs, tbslen) == 0) {
  147. ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SIGN);
  148. return 0;
  149. }
  150. *siglen = ED25519_SIGSIZE;
  151. return 1;
  152. }
  153. #endif /* S390X_EC_ASM */
  154. if (ossl_ed25519_sign(sigret, tbs, tbslen, edkey->pubkey, edkey->privkey,
  155. peddsactx->libctx, NULL) == 0) {
  156. ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SIGN);
  157. return 0;
  158. }
  159. *siglen = ED25519_SIGSIZE;
  160. return 1;
  161. }
  162. int ed448_digest_sign(void *vpeddsactx, unsigned char *sigret,
  163. size_t *siglen, size_t sigsize,
  164. const unsigned char *tbs, size_t tbslen)
  165. {
  166. PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
  167. const ECX_KEY *edkey = peddsactx->key;
  168. if (!ossl_prov_is_running())
  169. return 0;
  170. if (sigret == NULL) {
  171. *siglen = ED448_SIGSIZE;
  172. return 1;
  173. }
  174. if (sigsize < ED448_SIGSIZE) {
  175. ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
  176. return 0;
  177. }
  178. if (edkey->privkey == NULL) {
  179. ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY);
  180. return 0;
  181. }
  182. #ifdef S390X_EC_ASM
  183. if (S390X_CAN_SIGN(ED448)) {
  184. if (s390x_ed448_digestsign(edkey, sigret, tbs, tbslen) == 0) {
  185. ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SIGN);
  186. return 0;
  187. }
  188. *siglen = ED448_SIGSIZE;
  189. return 1;
  190. }
  191. #endif /* S390X_EC_ASM */
  192. if (ossl_ed448_sign(peddsactx->libctx, sigret, tbs, tbslen, edkey->pubkey,
  193. edkey->privkey, NULL, 0, edkey->propq) == 0) {
  194. ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SIGN);
  195. return 0;
  196. }
  197. *siglen = ED448_SIGSIZE;
  198. return 1;
  199. }
  200. int ed25519_digest_verify(void *vpeddsactx, const unsigned char *sig,
  201. size_t siglen, const unsigned char *tbs,
  202. size_t tbslen)
  203. {
  204. PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
  205. const ECX_KEY *edkey = peddsactx->key;
  206. if (!ossl_prov_is_running() || siglen != ED25519_SIGSIZE)
  207. return 0;
  208. #ifdef S390X_EC_ASM
  209. if (S390X_CAN_SIGN(ED25519))
  210. return s390x_ed25519_digestverify(edkey, sig, tbs, tbslen);
  211. #endif /* S390X_EC_ASM */
  212. return ossl_ed25519_verify(tbs, tbslen, sig, edkey->pubkey,
  213. peddsactx->libctx, edkey->propq);
  214. }
  215. int ed448_digest_verify(void *vpeddsactx, const unsigned char *sig,
  216. size_t siglen, const unsigned char *tbs,
  217. size_t tbslen)
  218. {
  219. PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
  220. const ECX_KEY *edkey = peddsactx->key;
  221. if (!ossl_prov_is_running() || siglen != ED448_SIGSIZE)
  222. return 0;
  223. #ifdef S390X_EC_ASM
  224. if (S390X_CAN_SIGN(ED448))
  225. return s390x_ed448_digestverify(edkey, sig, tbs, tbslen);
  226. #endif /* S390X_EC_ASM */
  227. return ossl_ed448_verify(peddsactx->libctx, tbs, tbslen, sig, edkey->pubkey,
  228. NULL, 0, edkey->propq);
  229. }
  230. static void eddsa_freectx(void *vpeddsactx)
  231. {
  232. PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
  233. ossl_ecx_key_free(peddsactx->key);
  234. OPENSSL_free(peddsactx);
  235. }
  236. static void *eddsa_dupctx(void *vpeddsactx)
  237. {
  238. PROV_EDDSA_CTX *srcctx = (PROV_EDDSA_CTX *)vpeddsactx;
  239. PROV_EDDSA_CTX *dstctx;
  240. if (!ossl_prov_is_running())
  241. return NULL;
  242. dstctx = OPENSSL_zalloc(sizeof(*srcctx));
  243. if (dstctx == NULL)
  244. return NULL;
  245. *dstctx = *srcctx;
  246. dstctx->key = NULL;
  247. if (srcctx->key != NULL && !ossl_ecx_key_up_ref(srcctx->key)) {
  248. ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
  249. goto err;
  250. }
  251. dstctx->key = srcctx->key;
  252. return dstctx;
  253. err:
  254. eddsa_freectx(dstctx);
  255. return NULL;
  256. }
  257. static int eddsa_get_ctx_params(void *vpeddsactx, OSSL_PARAM *params)
  258. {
  259. PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
  260. OSSL_PARAM *p;
  261. if (peddsactx == NULL)
  262. return 0;
  263. p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_ALGORITHM_ID);
  264. if (p != NULL && !OSSL_PARAM_set_octet_string(p, peddsactx->aid,
  265. peddsactx->aid_len))
  266. return 0;
  267. return 1;
  268. }
  269. static const OSSL_PARAM known_gettable_ctx_params[] = {
  270. OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_ALGORITHM_ID, NULL, 0),
  271. OSSL_PARAM_END
  272. };
  273. static const OSSL_PARAM *eddsa_gettable_ctx_params(ossl_unused void *vpeddsactx,
  274. ossl_unused void *provctx)
  275. {
  276. return known_gettable_ctx_params;
  277. }
  278. const OSSL_DISPATCH ossl_ed25519_signature_functions[] = {
  279. { OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))eddsa_newctx },
  280. { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT,
  281. (void (*)(void))eddsa_digest_signverify_init },
  282. { OSSL_FUNC_SIGNATURE_DIGEST_SIGN,
  283. (void (*)(void))ed25519_digest_sign },
  284. { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT,
  285. (void (*)(void))eddsa_digest_signverify_init },
  286. { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY,
  287. (void (*)(void))ed25519_digest_verify },
  288. { OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))eddsa_freectx },
  289. { OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))eddsa_dupctx },
  290. { OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, (void (*)(void))eddsa_get_ctx_params },
  291. { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS,
  292. (void (*)(void))eddsa_gettable_ctx_params },
  293. { 0, NULL }
  294. };
  295. const OSSL_DISPATCH ossl_ed448_signature_functions[] = {
  296. { OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))eddsa_newctx },
  297. { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT,
  298. (void (*)(void))eddsa_digest_signverify_init },
  299. { OSSL_FUNC_SIGNATURE_DIGEST_SIGN,
  300. (void (*)(void))ed448_digest_sign },
  301. { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT,
  302. (void (*)(void))eddsa_digest_signverify_init },
  303. { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY,
  304. (void (*)(void))ed448_digest_verify },
  305. { OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))eddsa_freectx },
  306. { OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))eddsa_dupctx },
  307. { OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, (void (*)(void))eddsa_get_ctx_params },
  308. { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS,
  309. (void (*)(void))eddsa_gettable_ctx_params },
  310. { 0, NULL }
  311. };
  312. #ifdef S390X_EC_ASM
  313. static int s390x_ed25519_digestsign(const ECX_KEY *edkey, unsigned char *sig,
  314. const unsigned char *tbs, size_t tbslen)
  315. {
  316. int rc;
  317. union {
  318. struct {
  319. unsigned char sig[64];
  320. unsigned char priv[32];
  321. } ed25519;
  322. unsigned long long buff[512];
  323. } param;
  324. memset(&param, 0, sizeof(param));
  325. memcpy(param.ed25519.priv, edkey->privkey, sizeof(param.ed25519.priv));
  326. rc = s390x_kdsa(S390X_EDDSA_SIGN_ED25519, &param.ed25519, tbs, tbslen);
  327. OPENSSL_cleanse(param.ed25519.priv, sizeof(param.ed25519.priv));
  328. if (rc != 0)
  329. return 0;
  330. s390x_flip_endian32(sig, param.ed25519.sig);
  331. s390x_flip_endian32(sig + 32, param.ed25519.sig + 32);
  332. return 1;
  333. }
  334. static int s390x_ed448_digestsign(const ECX_KEY *edkey, unsigned char *sig,
  335. const unsigned char *tbs, size_t tbslen)
  336. {
  337. int rc;
  338. union {
  339. struct {
  340. unsigned char sig[128];
  341. unsigned char priv[64];
  342. } ed448;
  343. unsigned long long buff[512];
  344. } param;
  345. memset(&param, 0, sizeof(param));
  346. memcpy(param.ed448.priv + 64 - 57, edkey->privkey, 57);
  347. rc = s390x_kdsa(S390X_EDDSA_SIGN_ED448, &param.ed448, tbs, tbslen);
  348. OPENSSL_cleanse(param.ed448.priv, sizeof(param.ed448.priv));
  349. if (rc != 0)
  350. return 0;
  351. s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
  352. s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
  353. memcpy(sig, param.ed448.sig, 57);
  354. memcpy(sig + 57, param.ed448.sig + 64, 57);
  355. return 1;
  356. }
  357. static int s390x_ed25519_digestverify(const ECX_KEY *edkey,
  358. const unsigned char *sig,
  359. const unsigned char *tbs, size_t tbslen)
  360. {
  361. union {
  362. struct {
  363. unsigned char sig[64];
  364. unsigned char pub[32];
  365. } ed25519;
  366. unsigned long long buff[512];
  367. } param;
  368. memset(&param, 0, sizeof(param));
  369. s390x_flip_endian32(param.ed25519.sig, sig);
  370. s390x_flip_endian32(param.ed25519.sig + 32, sig + 32);
  371. s390x_flip_endian32(param.ed25519.pub, edkey->pubkey);
  372. return s390x_kdsa(S390X_EDDSA_VERIFY_ED25519,
  373. &param.ed25519, tbs, tbslen) == 0 ? 1 : 0;
  374. }
  375. static int s390x_ed448_digestverify(const ECX_KEY *edkey,
  376. const unsigned char *sig,
  377. const unsigned char *tbs,
  378. size_t tbslen)
  379. {
  380. union {
  381. struct {
  382. unsigned char sig[128];
  383. unsigned char pub[64];
  384. } ed448;
  385. unsigned long long buff[512];
  386. } param;
  387. memset(&param, 0, sizeof(param));
  388. memcpy(param.ed448.sig, sig, 57);
  389. s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
  390. memcpy(param.ed448.sig + 64, sig + 57, 57);
  391. s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
  392. memcpy(param.ed448.pub, edkey->pubkey, 57);
  393. s390x_flip_endian64(param.ed448.pub, param.ed448.pub);
  394. return s390x_kdsa(S390X_EDDSA_VERIFY_ED448,
  395. &param.ed448, tbs, tbslen) == 0 ? 1 : 0;
  396. }
  397. #endif /* S390X_EC_ASM */