aes-select.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  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_IMPL(mode_c, id, mode_display, bits, required_mac, flags) /*WINSCP*/ \
  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, NULL, \
  49. /*.ssh2_id =*/ id, \
  50. /*.blksize =*/ 16, \
  51. /*.real_keybits =*/ bits, \
  52. /*.padded_keybytes =*/ bits/8, \
  53. flags, \
  54. /*.text_name =*/ "AES-" #bits " " mode_display \
  55. " (dummy selector vtable)", \
  56. required_mac, /*WINSCP*/ \
  57. /*.extra =*/ ssh_aes ## bits ## _ ## mode_c ## _impls, \
  58. }
  59. // WINSCP
  60. #define AES_SELECTOR_VTABLE(mode_c, id, mode_display, bits, dummy) AES_SELECTOR_VTABLE_IMPL(mode_c, id, mode_display, bits, NULL, 0)
  61. AES_SELECTOR_VTABLE_IMPL(cbc, "aes128-cbc", "CBC", 128, NULL, /*.flags =*/ SSH_CIPHER_IS_CBC);
  62. AES_SELECTOR_VTABLE_IMPL(cbc, "aes192-cbc", "CBC", 192, NULL, /*.flags =*/ SSH_CIPHER_IS_CBC);
  63. AES_SELECTOR_VTABLE_IMPL(cbc, "aes256-cbc", "CBC", 256, NULL, /*.flags =*/ SSH_CIPHER_IS_CBC);
  64. AES_SELECTOR_VTABLE(sdctr, "aes128-ctr", "SDCTR", 128, );
  65. AES_SELECTOR_VTABLE(sdctr, "aes192-ctr", "SDCTR", 192, );
  66. AES_SELECTOR_VTABLE(sdctr, "aes256-ctr", "SDCTR", 256, );
  67. AES_SELECTOR_VTABLE_IMPL(gcm, "[email protected]", "GCM", 128,
  68. /*.required_mac =*/ &ssh2_aesgcm_mac,
  69. /*.flags =*/ SSH_CIPHER_SEPARATE_LENGTH);
  70. AES_SELECTOR_VTABLE_IMPL(gcm, "[email protected]", "GCM", 256,
  71. /*.required_mac =*/ &ssh2_aesgcm_mac,
  72. /*.flags =*/ SSH_CIPHER_SEPARATE_LENGTH);
  73. /* 192-bit AES-GCM is included only so that testcrypt can run standard
  74. * test vectors against it. OpenSSH doesn't define a protocol id for
  75. * it. Hence setting its ssh2_id to NULL here, and more importantly,
  76. * leaving it out of aesgcm_list[] below. */
  77. AES_SELECTOR_VTABLE_IMPL(gcm, NULL, "GCM", 192,
  78. /*.required_mac =*/ &ssh2_aesgcm_mac,
  79. /*.flags =*/ SSH_CIPHER_SEPARATE_LENGTH);
  80. static const ssh_cipheralg ssh_rijndael_lysator = {
  81. /* Same as aes256_cbc, but with a different protocol ID */
  82. /*.new =*/ aes_select,
  83. NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  84. /*.ssh2_id =*/ "[email protected]",
  85. /*.blksize =*/ 16,
  86. /*.real_keybits =*/ 256,
  87. /*.padded_keybytes =*/ 256/8,
  88. /*.flags =*/ SSH_CIPHER_IS_CBC,
  89. /*.text_name =*/ "AES-256 CBC (dummy selector vtable)",
  90. NULL,
  91. /*.extra =*/ ssh_aes256_cbc_impls,
  92. };
  93. static const ssh_cipheralg *const aes_list[] = {
  94. &ssh_aes256_sdctr,
  95. &ssh_aes256_cbc,
  96. &ssh_rijndael_lysator,
  97. &ssh_aes192_sdctr,
  98. &ssh_aes192_cbc,
  99. &ssh_aes128_sdctr,
  100. &ssh_aes128_cbc,
  101. };
  102. const ssh2_ciphers ssh2_aes = { lenof(aes_list), aes_list };
  103. static const ssh_cipheralg *const aesgcm_list[] = {
  104. /* OpenSSH only defines protocol ids for 128- and 256-bit AES-GCM,
  105. * not 192-bit. */
  106. &ssh_aes128_gcm,
  107. &ssh_aes256_gcm,
  108. };
  109. const ssh2_ciphers ssh2_aesgcm = { lenof(aesgcm_list), aesgcm_list };