bn_s390x.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. /*
  2. * Copyright 2023 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 "crypto/bn.h"
  10. #include "crypto/s390x_arch.h"
  11. #ifdef S390X_MOD_EXP
  12. # include <sys/types.h>
  13. # include <sys/stat.h>
  14. # include <fcntl.h>
  15. # include <asm/zcrypt.h>
  16. # include <sys/ioctl.h>
  17. # include <unistd.h>
  18. # include <errno.h>
  19. static int s390x_mod_exp_hw(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
  20. const BIGNUM *m)
  21. {
  22. struct ica_rsa_modexpo me;
  23. unsigned char *buffer;
  24. size_t size;
  25. int res = 0;
  26. if (OPENSSL_s390xcex == -1 || OPENSSL_s390xcex_nodev)
  27. return 0;
  28. size = BN_num_bytes(m);
  29. buffer = OPENSSL_zalloc(4 * size);
  30. if (buffer == NULL)
  31. return 0;
  32. me.inputdata = buffer;
  33. me.inputdatalength = size;
  34. me.outputdata = buffer + size;
  35. me.outputdatalength = size;
  36. me.b_key = buffer + 2 * size;
  37. me.n_modulus = buffer + 3 * size;
  38. if (BN_bn2binpad(a, me.inputdata, size) == -1
  39. || BN_bn2binpad(p, me.b_key, size) == -1
  40. || BN_bn2binpad(m, me.n_modulus, size) == -1)
  41. goto dealloc;
  42. if (ioctl(OPENSSL_s390xcex, ICARSAMODEXPO, &me) != -1) {
  43. if (BN_bin2bn(me.outputdata, size, r) != NULL)
  44. res = 1;
  45. } else if (errno == EBADF || errno == ENOTTY) {
  46. /*
  47. * In this cases, someone (e.g. a sandbox) closed the fd.
  48. * Make sure to not further use this hardware acceleration.
  49. * In case of ENOTTY the file descriptor was already reused for another
  50. * file. Do not attempt to use or close that file descriptor anymore.
  51. */
  52. OPENSSL_s390xcex = -1;
  53. } else if (errno == ENODEV) {
  54. /*
  55. * No crypto card(s) available to handle RSA requests.
  56. * Make sure to not further use this hardware acceleration,
  57. * but do not close the file descriptor.
  58. */
  59. OPENSSL_s390xcex_nodev = 1;
  60. }
  61. dealloc:
  62. OPENSSL_clear_free(buffer, 4 * size);
  63. return res;
  64. }
  65. int s390x_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
  66. const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
  67. {
  68. if (s390x_mod_exp_hw(r, a, p, m) == 1)
  69. return 1;
  70. return BN_mod_exp_mont(r, a, p, m, ctx, m_ctx);
  71. }
  72. int s390x_crt(BIGNUM *r, const BIGNUM *i, const BIGNUM *p, const BIGNUM *q,
  73. const BIGNUM *dmp, const BIGNUM *dmq, const BIGNUM *iqmp)
  74. {
  75. struct ica_rsa_modexpo_crt crt;
  76. unsigned char *buffer, *part;
  77. size_t size, plen, qlen;
  78. int res = 0;
  79. if (OPENSSL_s390xcex == -1 || OPENSSL_s390xcex_nodev)
  80. return 0;
  81. /*-
  82. * Hardware-accelerated CRT can only deal with p>q. Fall back to
  83. * software in the (hopefully rare) other cases.
  84. */
  85. if (BN_ucmp(p, q) != 1)
  86. return 0;
  87. plen = BN_num_bytes(p);
  88. qlen = BN_num_bytes(q);
  89. size = (plen > qlen ? plen : qlen);
  90. buffer = OPENSSL_zalloc(9 * size + 24);
  91. if (buffer == NULL)
  92. return 0;
  93. part = buffer;
  94. crt.inputdata = part;
  95. crt.inputdatalength = 2 * size;
  96. part += 2 * size;
  97. crt.outputdata = part;
  98. crt.outputdatalength = 2 * size;
  99. part += 2 * size;
  100. crt.bp_key = part;
  101. part += size + 8;
  102. crt.bq_key = part;
  103. part += size;
  104. crt.np_prime = part;
  105. part += size + 8;
  106. crt.nq_prime = part;
  107. part += size;
  108. crt.u_mult_inv = part;
  109. if (BN_bn2binpad(i, crt.inputdata, crt.inputdatalength) == -1
  110. || BN_bn2binpad(p, crt.np_prime, size + 8) == -1
  111. || BN_bn2binpad(q, crt.nq_prime, size) == -1
  112. || BN_bn2binpad(dmp, crt.bp_key, size + 8) == -1
  113. || BN_bn2binpad(dmq, crt.bq_key, size) == -1
  114. || BN_bn2binpad(iqmp, crt.u_mult_inv, size + 8) == -1)
  115. goto dealloc;
  116. if (ioctl(OPENSSL_s390xcex, ICARSACRT, &crt) != -1) {
  117. if (BN_bin2bn(crt.outputdata, crt.outputdatalength, r) != NULL)
  118. res = 1;
  119. } else if (errno == EBADF || errno == ENOTTY) {
  120. /*
  121. * In this cases, someone (e.g. a sandbox) closed the fd.
  122. * Make sure to not further use this hardware acceleration.
  123. * In case of ENOTTY the file descriptor was already reused for another
  124. * file. Do not attempt to use or close that file descriptor anymore.
  125. */
  126. OPENSSL_s390xcex = -1;
  127. } else if (errno == ENODEV) {
  128. /*
  129. * No crypto card(s) available to handle RSA requests.
  130. * Make sure to not further use this hardware acceleration,
  131. * but do not close the file descriptor.
  132. */
  133. OPENSSL_s390xcex_nodev = 1;
  134. }
  135. dealloc:
  136. OPENSSL_clear_free(buffer, 9 * size + 24);
  137. return res;
  138. }
  139. #else
  140. int s390x_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
  141. const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
  142. {
  143. return BN_mod_exp_mont(r, a, p, m, ctx, m_ctx);
  144. }
  145. int s390x_crt(BIGNUM *r, const BIGNUM *i, const BIGNUM *p, const BIGNUM *q,
  146. const BIGNUM *dmp, const BIGNUM *dmq, const BIGNUM *iqmp)
  147. {
  148. return 0;
  149. }
  150. #endif