aes-select.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. /*
  2. * Top-level vtables to select an AES implementation.
  3. */
  4. #include <assert.h>
  5. #include <stdlib.h>
  6. #include "putty.h"
  7. #include "ssh.h"
  8. #include "aes.h"
  9. static ssh_cipher *aes_select(const ssh_cipheralg *alg)
  10. {
  11. const ssh_cipheralg *const *real_algs = (const ssh_cipheralg **)alg->extra;
  12. { // WINSCP
  13. size_t i;
  14. for (i = 0; real_algs[i]; i++) {
  15. const ssh_cipheralg *alg = real_algs[i];
  16. const struct aes_extra *alg_extra =
  17. (const struct aes_extra *)alg->extra;
  18. if (check_availability(alg_extra))
  19. return ssh_cipher_new(alg);
  20. }
  21. /* We should never reach the NULL at the end of the list, because
  22. * the last non-NULL entry should be software-only AES, which is
  23. * always available. */
  24. unreachable("aes_select ran off the end of its list");
  25. } // WINSCP
  26. }
  27. #if HAVE_AES_NI
  28. #define IF_NI(...) __VA_ARGS__
  29. #else
  30. #define IF_NI(...)
  31. #endif
  32. #if HAVE_NEON_CRYPTO
  33. #define IF_NEON(...) __VA_ARGS__
  34. #else
  35. #define IF_NEON(...)
  36. #endif
  37. #define AES_SELECTOR_VTABLE(mode_c, id, mode_display, bits, ...) \
  38. static const ssh_cipheralg * \
  39. ssh_aes ## bits ## _ ## mode_c ## _impls[] = { \
  40. IF_NI(&ssh_aes ## bits ## _ ## mode_c ## _ni,) \
  41. IF_NEON(&ssh_aes ## bits ## _ ## mode_c ## _neon,) \
  42. &ssh_aes ## bits ## _ ## mode_c ## _sw, \
  43. NULL, \
  44. }; \
  45. const ssh_cipheralg ssh_aes ## bits ## _ ## mode_c = { \
  46. /* WINSCP */ \
  47. /*.new =*/ aes_select, \
  48. NULL, NULL, NULL, NULL, NULL, NULL, NULL, \
  49. /*.ssh2_id =*/ id \
  50. /*.blksize =*/ 16, \
  51. /*.real_keybits =*/ bits, \
  52. /*.padded_keybytes =*/ bits/8, \
  53. 0, \
  54. /*.text_name =*/ "AES-" #bits " " mode_display \
  55. " (dummy selector vtable)", \
  56. NULL, \
  57. /*.extra =*/ ssh_aes ## bits ## _ ## mode_c ## _impls, \
  58. __VA_ARGS__ \
  59. }
  60. AES_SELECTOR_VTABLE(cbc, "aes128-cbc", "CBC", 128, );
  61. AES_SELECTOR_VTABLE(cbc, "aes192-cbc", "CBC", 192, );
  62. AES_SELECTOR_VTABLE(cbc, "aes256-cbc", "CBC", 256, );
  63. AES_SELECTOR_VTABLE(sdctr, "aes128-ctr", "SDCTR", 128, );
  64. AES_SELECTOR_VTABLE(sdctr, "aes192-ctr", "SDCTR", 192, );
  65. AES_SELECTOR_VTABLE(sdctr, "aes256-ctr", "SDCTR", 256, );
  66. AES_SELECTOR_VTABLE(gcm, "[email protected]", "GCM", 128,
  67. .required_mac = &ssh2_aesgcm_mac);
  68. AES_SELECTOR_VTABLE(gcm, "[email protected]", "GCM", 256,
  69. .required_mac = &ssh2_aesgcm_mac);
  70. /* 192-bit AES-GCM is included only so that testcrypt can run standard
  71. * test vectors against it. OpenSSH doesn't define a protocol id for
  72. * it. Hence setting its ssh2_id to NULL here, and more importantly,
  73. * leaving it out of aesgcm_list[] below. */
  74. AES_SELECTOR_VTABLE(gcm, NULL, "GCM", 192,
  75. .required_mac = &ssh2_aesgcm_mac);
  76. static const ssh_cipheralg ssh_rijndael_lysator = {
  77. /* Same as aes256_cbc, but with a different protocol ID */
  78. /*.new =*/ aes_select,
  79. NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  80. /*.ssh2_id =*/ "[email protected]",
  81. /*.blksize =*/ 16,
  82. /*.real_keybits =*/ 256,
  83. /*.padded_keybytes =*/ 256/8,
  84. 0,
  85. /*.text_name =*/ "AES-256 CBC (dummy selector vtable)",
  86. NULL,
  87. /*.extra =*/ ssh_aes256_cbc_impls,
  88. };
  89. static const ssh_cipheralg *const aes_list[] = {
  90. &ssh_aes256_sdctr,
  91. &ssh_aes256_cbc,
  92. &ssh_rijndael_lysator,
  93. &ssh_aes192_sdctr,
  94. &ssh_aes192_cbc,
  95. &ssh_aes128_sdctr,
  96. &ssh_aes128_cbc,
  97. };
  98. const ssh2_ciphers ssh2_aes = { lenof(aes_list), aes_list };
  99. static const ssh_cipheralg *const aesgcm_list[] = {
  100. /* OpenSSH only defines protocol ids for 128- and 256-bit AES-GCM,
  101. * not 192-bit. */
  102. &ssh_aes128_gcm,
  103. &ssh_aes256_gcm,
  104. };
  105. const ssh2_ciphers ssh2_aesgcm = { lenof(aesgcm_list), aesgcm_list };