Reference implementations of PQC
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

147 lines
4.2 KiB

  1. import glob
  2. import os
  3. import yaml
  4. class Scheme:
  5. def __init__(self):
  6. self.type = None
  7. self.name = None
  8. self.implementations = []
  9. def path(self, base='..'):
  10. return os.path.join(base, 'crypto_' + self.type, self.name)
  11. def namespace_prefix(self):
  12. return 'PQCLEAN_{}_'.format(self.name.upper()).replace('-', '')
  13. @staticmethod
  14. def by_name(scheme_name):
  15. for scheme in Scheme.all_schemes():
  16. if scheme.name == scheme_name:
  17. return scheme
  18. raise KeyError()
  19. @staticmethod
  20. def all_schemes():
  21. schemes = []
  22. schemes.extend(Scheme.all_schemes_of_type('kem'))
  23. schemes.extend(Scheme.all_schemes_of_type('sign'))
  24. return schemes
  25. @staticmethod
  26. def all_implementations():
  27. implementations = []
  28. for scheme in Scheme.all_schemes():
  29. implementations.extend(scheme.implementations)
  30. return implementations
  31. @staticmethod
  32. def all_schemes_of_type(type: str) -> list:
  33. schemes = []
  34. p = os.path.join('..', 'crypto_' + type)
  35. if os.path.isdir(p):
  36. for d in os.listdir(p):
  37. if os.path.isdir(os.path.join(p, d)):
  38. if type == 'kem':
  39. schemes.append(KEM(d))
  40. elif type == 'sign':
  41. schemes.append(Signature(d))
  42. else:
  43. assert('Unknown type')
  44. return schemes
  45. def metadata(self):
  46. metafile = os.path.join(self.path(), 'META.yml')
  47. try:
  48. with open(metafile, encoding='utf-8') as f:
  49. metadata = yaml.safe_load(f.read())
  50. return metadata
  51. except Exception as e:
  52. print("Can't open {}: {}".format(metafile, e))
  53. return None
  54. def __repr__(self):
  55. return "<{}({})>".format(self.type.title(), self.name)
  56. class Implementation:
  57. def __init__(self, scheme, name):
  58. self.scheme = scheme
  59. self.name = name
  60. def metadata(self):
  61. for i in self.scheme.metadata()['implementations']:
  62. if i['name'] == self.name:
  63. return i
  64. def path(self, base='..') -> str:
  65. return os.path.join(self.scheme.path(base=base), self.name)
  66. def libname(self) -> str:
  67. if os.name == 'nt':
  68. return "lib{}_{}.lib".format(self.scheme.name, self.name)
  69. return "lib{}_{}.a".format(self.scheme.name, self.name)
  70. def cfiles(self) -> [str]:
  71. return glob.glob(os.path.join(self.path(), '*.c'))
  72. def hfiles(self) -> [str]:
  73. return glob.glob(os.path.join(self.path(), '*.h'))
  74. def ofiles(self) -> [str]:
  75. return glob.glob(os.path.join(self.path(),
  76. '*.o' if os.name != 'nt' else '*.obj'))
  77. @staticmethod
  78. def by_name(scheme_name, implementation_name):
  79. scheme = Scheme.by_name(scheme_name)
  80. for implementation in scheme.implementations:
  81. if implementation.name == implementation_name:
  82. return implementation
  83. raise KeyError()
  84. @staticmethod
  85. def all_implementations(scheme: Scheme) -> list:
  86. implementations = []
  87. for d in os.listdir(scheme.path()):
  88. if os.path.isdir(os.path.join(scheme.path(), d)):
  89. implementations.append(Implementation(scheme, d))
  90. return implementations
  91. def namespace_prefix(self):
  92. return '{}{}_'.format(self.scheme.namespace_prefix(),
  93. self.name.upper()).replace('-', '')
  94. def __str__(self):
  95. return "{} implementation of {}".format(self.name, self.scheme.name)
  96. def __repr__(self):
  97. return "<Implementation({}, {})>".format(self.scheme.name, self.name)
  98. class KEM(Scheme):
  99. def __init__(self, name: str):
  100. self.type = 'kem'
  101. self.name = name
  102. self.implementations = Implementation.all_implementations(self)
  103. @staticmethod
  104. def all_kems() -> list:
  105. return Scheme.all_schemes_of_type('kem')
  106. class Signature(Scheme):
  107. def __init__(self, name: str):
  108. self.type = 'sign'
  109. self.name = name
  110. self.implementations = Implementation.all_implementations(self)
  111. @staticmethod
  112. def all_sigs():
  113. return Scheme.all_schemes_of_type('sign')