2
0

eddsa_sig.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  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. ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
  66. return NULL;
  67. }
  68. peddsactx->libctx = PROV_LIBCTX_OF(provctx);
  69. return peddsactx;
  70. }
  71. static int eddsa_digest_signverify_init(void *vpeddsactx, const char *mdname,
  72. void *vedkey,
  73. ossl_unused const OSSL_PARAM params[])
  74. {
  75. PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
  76. ECX_KEY *edkey = (ECX_KEY *)vedkey;
  77. WPACKET pkt;
  78. int ret;
  79. if (!ossl_prov_is_running())
  80. return 0;
  81. if (mdname != NULL && mdname[0] != '\0') {
  82. ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST);
  83. return 0;
  84. }
  85. if (edkey == NULL) {
  86. if (peddsactx->key != NULL)
  87. /* there is nothing to do on reinit */
  88. return 1;
  89. ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET);
  90. return 0;
  91. }
  92. if (!ossl_ecx_key_up_ref(edkey)) {
  93. ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
  94. return 0;
  95. }
  96. /*
  97. * We do not care about DER writing errors.
  98. * All it really means is that for some reason, there's no
  99. * AlgorithmIdentifier to be had, but the operation itself is
  100. * still valid, just as long as it's not used to construct
  101. * anything that needs an AlgorithmIdentifier.
  102. */
  103. peddsactx->aid_len = 0;
  104. ret = WPACKET_init_der(&pkt, peddsactx->aid_buf, sizeof(peddsactx->aid_buf));
  105. switch (edkey->type) {
  106. case ECX_KEY_TYPE_ED25519:
  107. ret = ret && ossl_DER_w_algorithmIdentifier_ED25519(&pkt, -1, edkey);
  108. break;
  109. case ECX_KEY_TYPE_ED448:
  110. ret = ret && ossl_DER_w_algorithmIdentifier_ED448(&pkt, -1, edkey);
  111. break;
  112. default:
  113. /* Should never happen */
  114. ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
  115. ossl_ecx_key_free(edkey);
  116. return 0;
  117. }
  118. if (ret && WPACKET_finish(&pkt)) {
  119. WPACKET_get_total_written(&pkt, &peddsactx->aid_len);
  120. peddsactx->aid = WPACKET_get_curr(&pkt);
  121. }
  122. WPACKET_cleanup(&pkt);
  123. peddsactx->key = edkey;
  124. return 1;
  125. }
  126. int ed25519_digest_sign(void *vpeddsactx, unsigned char *sigret,
  127. size_t *siglen, size_t sigsize,
  128. const unsigned char *tbs, size_t tbslen)
  129. {
  130. PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
  131. const ECX_KEY *edkey = peddsactx->key;
  132. if (!ossl_prov_is_running())
  133. return 0;
  134. if (sigret == NULL) {
  135. *siglen = ED25519_SIGSIZE;
  136. return 1;
  137. }
  138. if (sigsize < ED25519_SIGSIZE) {
  139. ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
  140. return 0;
  141. }
  142. #ifdef S390X_EC_ASM
  143. if (S390X_CAN_SIGN(ED25519)) {
  144. if (s390x_ed25519_digestsign(edkey, sigret, tbs, tbslen) == 0) {
  145. ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SIGN);
  146. return 0;
  147. }
  148. *siglen = ED25519_SIGSIZE;
  149. return 1;
  150. }
  151. #endif /* S390X_EC_ASM */
  152. if (ossl_ed25519_sign(sigret, tbs, tbslen, edkey->pubkey, edkey->privkey,
  153. peddsactx->libctx, NULL) == 0) {
  154. ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SIGN);
  155. return 0;
  156. }
  157. *siglen = ED25519_SIGSIZE;
  158. return 1;
  159. }
  160. int ed448_digest_sign(void *vpeddsactx, unsigned char *sigret,
  161. size_t *siglen, size_t sigsize,
  162. const unsigned char *tbs, size_t tbslen)
  163. {
  164. PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
  165. const ECX_KEY *edkey = peddsactx->key;
  166. if (!ossl_prov_is_running())
  167. return 0;
  168. if (sigret == NULL) {
  169. *siglen = ED448_SIGSIZE;
  170. return 1;
  171. }
  172. if (sigsize < ED448_SIGSIZE) {
  173. ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
  174. return 0;
  175. }
  176. #ifdef S390X_EC_ASM
  177. if (S390X_CAN_SIGN(ED448)) {
  178. if (s390x_ed448_digestsign(edkey, sigret, tbs, tbslen) == 0) {
  179. ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SIGN);
  180. return 0;
  181. }
  182. *siglen = ED448_SIGSIZE;
  183. return 1;
  184. }
  185. #endif /* S390X_EC_ASM */
  186. if (ossl_ed448_sign(peddsactx->libctx, sigret, tbs, tbslen, edkey->pubkey,
  187. edkey->privkey, NULL, 0, edkey->propq) == 0) {
  188. ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SIGN);
  189. return 0;
  190. }
  191. *siglen = ED448_SIGSIZE;
  192. return 1;
  193. }
  194. int ed25519_digest_verify(void *vpeddsactx, const unsigned char *sig,
  195. size_t siglen, const unsigned char *tbs,
  196. size_t tbslen)
  197. {
  198. PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
  199. const ECX_KEY *edkey = peddsactx->key;
  200. if (!ossl_prov_is_running() || siglen != ED25519_SIGSIZE)
  201. return 0;
  202. #ifdef S390X_EC_ASM
  203. if (S390X_CAN_SIGN(ED25519))
  204. return s390x_ed25519_digestverify(edkey, sig, tbs, tbslen);
  205. #endif /* S390X_EC_ASM */
  206. return ossl_ed25519_verify(tbs, tbslen, sig, edkey->pubkey,
  207. peddsactx->libctx, edkey->propq);
  208. }
  209. int ed448_digest_verify(void *vpeddsactx, const unsigned char *sig,
  210. size_t siglen, const unsigned char *tbs,
  211. size_t tbslen)
  212. {
  213. PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
  214. const ECX_KEY *edkey = peddsactx->key;
  215. if (!ossl_prov_is_running() || siglen != ED448_SIGSIZE)
  216. return 0;
  217. #ifdef S390X_EC_ASM
  218. if (S390X_CAN_SIGN(ED448))
  219. return s390x_ed448_digestverify(edkey, sig, tbs, tbslen);
  220. #endif /* S390X_EC_ASM */
  221. return ossl_ed448_verify(peddsactx->libctx, tbs, tbslen, sig, edkey->pubkey,
  222. NULL, 0, edkey->propq);
  223. }
  224. static void eddsa_freectx(void *vpeddsactx)
  225. {
  226. PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
  227. ossl_ecx_key_free(peddsactx->key);
  228. OPENSSL_free(peddsactx);
  229. }
  230. static void *eddsa_dupctx(void *vpeddsactx)
  231. {
  232. PROV_EDDSA_CTX *srcctx = (PROV_EDDSA_CTX *)vpeddsactx;
  233. PROV_EDDSA_CTX *dstctx;
  234. if (!ossl_prov_is_running())
  235. return NULL;
  236. dstctx = OPENSSL_zalloc(sizeof(*srcctx));
  237. if (dstctx == NULL)
  238. return NULL;
  239. *dstctx = *srcctx;
  240. dstctx->key = NULL;
  241. if (srcctx->key != NULL && !ossl_ecx_key_up_ref(srcctx->key)) {
  242. ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
  243. goto err;
  244. }
  245. dstctx->key = srcctx->key;
  246. return dstctx;
  247. err:
  248. eddsa_freectx(dstctx);
  249. return NULL;
  250. }
  251. static int eddsa_get_ctx_params(void *vpeddsactx, OSSL_PARAM *params)
  252. {
  253. PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
  254. OSSL_PARAM *p;
  255. if (peddsactx == NULL)
  256. return 0;
  257. p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_ALGORITHM_ID);
  258. if (p != NULL && !OSSL_PARAM_set_octet_string(p, peddsactx->aid,
  259. peddsactx->aid_len))
  260. return 0;
  261. return 1;
  262. }
  263. static const OSSL_PARAM known_gettable_ctx_params[] = {
  264. OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_ALGORITHM_ID, NULL, 0),
  265. OSSL_PARAM_END
  266. };
  267. static const OSSL_PARAM *eddsa_gettable_ctx_params(ossl_unused void *vpeddsactx,
  268. ossl_unused void *provctx)
  269. {
  270. return known_gettable_ctx_params;
  271. }
  272. const OSSL_DISPATCH ossl_ed25519_signature_functions[] = {
  273. { OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))eddsa_newctx },
  274. { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT,
  275. (void (*)(void))eddsa_digest_signverify_init },
  276. { OSSL_FUNC_SIGNATURE_DIGEST_SIGN,
  277. (void (*)(void))ed25519_digest_sign },
  278. { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT,
  279. (void (*)(void))eddsa_digest_signverify_init },
  280. { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY,
  281. (void (*)(void))ed25519_digest_verify },
  282. { OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))eddsa_freectx },
  283. { OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))eddsa_dupctx },
  284. { OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, (void (*)(void))eddsa_get_ctx_params },
  285. { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS,
  286. (void (*)(void))eddsa_gettable_ctx_params },
  287. { 0, NULL }
  288. };
  289. const OSSL_DISPATCH ossl_ed448_signature_functions[] = {
  290. { OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))eddsa_newctx },
  291. { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT,
  292. (void (*)(void))eddsa_digest_signverify_init },
  293. { OSSL_FUNC_SIGNATURE_DIGEST_SIGN,
  294. (void (*)(void))ed448_digest_sign },
  295. { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT,
  296. (void (*)(void))eddsa_digest_signverify_init },
  297. { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY,
  298. (void (*)(void))ed448_digest_verify },
  299. { OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))eddsa_freectx },
  300. { OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))eddsa_dupctx },
  301. { OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, (void (*)(void))eddsa_get_ctx_params },
  302. { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS,
  303. (void (*)(void))eddsa_gettable_ctx_params },
  304. { 0, NULL }
  305. };
  306. #ifdef S390X_EC_ASM
  307. static int s390x_ed25519_digestsign(const ECX_KEY *edkey, unsigned char *sig,
  308. const unsigned char *tbs, size_t tbslen)
  309. {
  310. int rc;
  311. union {
  312. struct {
  313. unsigned char sig[64];
  314. unsigned char priv[32];
  315. } ed25519;
  316. unsigned long long buff[512];
  317. } param;
  318. memset(&param, 0, sizeof(param));
  319. memcpy(param.ed25519.priv, edkey->privkey, sizeof(param.ed25519.priv));
  320. rc = s390x_kdsa(S390X_EDDSA_SIGN_ED25519, &param.ed25519, tbs, tbslen);
  321. OPENSSL_cleanse(param.ed25519.priv, sizeof(param.ed25519.priv));
  322. if (rc != 0)
  323. return 0;
  324. s390x_flip_endian32(sig, param.ed25519.sig);
  325. s390x_flip_endian32(sig + 32, param.ed25519.sig + 32);
  326. return 1;
  327. }
  328. static int s390x_ed448_digestsign(const ECX_KEY *edkey, unsigned char *sig,
  329. const unsigned char *tbs, size_t tbslen)
  330. {
  331. int rc;
  332. union {
  333. struct {
  334. unsigned char sig[128];
  335. unsigned char priv[64];
  336. } ed448;
  337. unsigned long long buff[512];
  338. } param;
  339. memset(&param, 0, sizeof(param));
  340. memcpy(param.ed448.priv + 64 - 57, edkey->privkey, 57);
  341. rc = s390x_kdsa(S390X_EDDSA_SIGN_ED448, &param.ed448, tbs, tbslen);
  342. OPENSSL_cleanse(param.ed448.priv, sizeof(param.ed448.priv));
  343. if (rc != 0)
  344. return 0;
  345. s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
  346. s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
  347. memcpy(sig, param.ed448.sig, 57);
  348. memcpy(sig + 57, param.ed448.sig + 64, 57);
  349. return 1;
  350. }
  351. static int s390x_ed25519_digestverify(const ECX_KEY *edkey,
  352. const unsigned char *sig,
  353. const unsigned char *tbs, size_t tbslen)
  354. {
  355. union {
  356. struct {
  357. unsigned char sig[64];
  358. unsigned char pub[32];
  359. } ed25519;
  360. unsigned long long buff[512];
  361. } param;
  362. memset(&param, 0, sizeof(param));
  363. s390x_flip_endian32(param.ed25519.sig, sig);
  364. s390x_flip_endian32(param.ed25519.sig + 32, sig + 32);
  365. s390x_flip_endian32(param.ed25519.pub, edkey->pubkey);
  366. return s390x_kdsa(S390X_EDDSA_VERIFY_ED25519,
  367. &param.ed25519, tbs, tbslen) == 0 ? 1 : 0;
  368. }
  369. static int s390x_ed448_digestverify(const ECX_KEY *edkey,
  370. const unsigned char *sig,
  371. const unsigned char *tbs,
  372. size_t tbslen)
  373. {
  374. union {
  375. struct {
  376. unsigned char sig[128];
  377. unsigned char pub[64];
  378. } ed448;
  379. unsigned long long buff[512];
  380. } param;
  381. memset(&param, 0, sizeof(param));
  382. memcpy(param.ed448.sig, sig, 57);
  383. s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
  384. memcpy(param.ed448.sig + 64, sig + 57, 57);
  385. s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
  386. memcpy(param.ed448.pub, edkey->pubkey, 57);
  387. s390x_flip_endian64(param.ed448.pub, param.ed448.pub);
  388. return s390x_kdsa(S390X_EDDSA_VERIFY_ED448,
  389. &param.ed448, tbs, tbslen) == 0 ? 1 : 0;
  390. }
  391. #endif /* S390X_EC_ASM */