diff options
author | Justin Coffman <coffmanjk@gmail.com> | 2018-06-22 11:13:09 -0400 |
---|---|---|
committer | Justin Coffman <coffmanjk@gmail.com> | 2018-06-22 11:13:09 -0400 |
commit | 3efa35305eb8c1852fbf15ecd5cbc6fff08b272f (patch) | |
tree | f52e40e5d30977d2bb76a923a6b2bcb756601032 /tools/scripts | |
parent | 3937cbaa88eaee9459acc4a959e73b7d8863bbf9 (diff) | |
download | pfsense-3efa35305eb8c1852fbf15ecd5cbc6fff08b272f.zip pfsense-3efa35305eb8c1852fbf15ecd5cbc6fff08b272f.tar.gz |
Provide DH groups from RFC 7919.
Replaced 2048-bit and 4096-bit groups with RFC 7919 parameters. Added 3072, 6144, and 8192-bit groups from same. Relocated PEM generator script to tools directory.
Diffstat (limited to 'tools/scripts')
-rwxr-xr-x | tools/scripts/generate_ffdhe.py | 418 |
1 files changed, 418 insertions, 0 deletions
diff --git a/tools/scripts/generate_ffdhe.py b/tools/scripts/generate_ffdhe.py new file mode 100755 index 0000000..107bcec --- /dev/null +++ b/tools/scripts/generate_ffdhe.py @@ -0,0 +1,418 @@ +#!/usr/bin/env python +# +# generate-ffdhe.py +# +# Generate PEM strings for the FFDHE parameters in RFC 7919 +# For reference, see https://tools.ietf.org/rfc/rfc7919.txt +# +# This is derived from a similar script from the Mumble project. +# https://github.com/mumble-voip/mumble/blob/master/scripts/generate-ffdhe.py + +from __future__ import (unicode_literals, print_function, division) + +# Python 3 doesn't have a long type. +# Map the long type to int here, so +# we can easily be compatible with both +# interpreters. +try: + type(long) +except NameError: + long = int + +import os +import base64 +import codecs + +# The following P values are directly sourced from RFC 7919 at +# https://tools.ietf.org/rfc/rfc7919.txt + +ffdhe_str = { + '2048': ''' + FFFFFFFF FFFFFFFF ADF85458 A2BB4A9A AFDC5620 273D3CF1 + D8B9C583 CE2D3695 A9E13641 146433FB CC939DCE 249B3EF9 + 7D2FE363 630C75D8 F681B202 AEC4617A D3DF1ED5 D5FD6561 + 2433F51F 5F066ED0 85636555 3DED1AF3 B557135E 7F57C935 + 984F0C70 E0E68B77 E2A689DA F3EFE872 1DF158A1 36ADE735 + 30ACCA4F 483A797A BC0AB182 B324FB61 D108A94B B2C8E3FB + B96ADAB7 60D7F468 1D4F42A3 DE394DF4 AE56EDE7 6372BB19 + 0B07A7C8 EE0A6D70 9E02FCE1 CDF7E2EC C03404CD 28342F61 + 9172FE9C E98583FF 8E4F1232 EEF28183 C3FE3B1B 4C6FAD73 + 3BB5FCBC 2EC22005 C58EF183 7D1683B2 C6F34A26 C1B2EFFA + 886B4238 61285C97 FFFFFFFF FFFFFFFF + ''', + '3072': ''' + FFFFFFFF FFFFFFFF ADF85458 A2BB4A9A AFDC5620 273D3CF1 + D8B9C583 CE2D3695 A9E13641 146433FB CC939DCE 249B3EF9 + 7D2FE363 630C75D8 F681B202 AEC4617A D3DF1ED5 D5FD6561 + 2433F51F 5F066ED0 85636555 3DED1AF3 B557135E 7F57C935 + 984F0C70 E0E68B77 E2A689DA F3EFE872 1DF158A1 36ADE735 + 30ACCA4F 483A797A BC0AB182 B324FB61 D108A94B B2C8E3FB + B96ADAB7 60D7F468 1D4F42A3 DE394DF4 AE56EDE7 6372BB19 + 0B07A7C8 EE0A6D70 9E02FCE1 CDF7E2EC C03404CD 28342F61 + 9172FE9C E98583FF 8E4F1232 EEF28183 C3FE3B1B 4C6FAD73 + 3BB5FCBC 2EC22005 C58EF183 7D1683B2 C6F34A26 C1B2EFFA + 886B4238 611FCFDC DE355B3B 6519035B BC34F4DE F99C0238 + 61B46FC9 D6E6C907 7AD91D26 91F7F7EE 598CB0FA C186D91C + AEFE1309 85139270 B4130C93 BC437944 F4FD4452 E2D74DD3 + 64F2E21E 71F54BFF 5CAE82AB 9C9DF69E E86D2BC5 22363A0D + ABC52197 9B0DEADA 1DBF9A42 D5C4484E 0ABCD06B FA53DDEF + 3C1B20EE 3FD59D7C 25E41D2B 66C62E37 FFFFFFFF FFFFFFFF + ''', + '4096': ''' + FFFFFFFF FFFFFFFF ADF85458 A2BB4A9A AFDC5620 273D3CF1 + D8B9C583 CE2D3695 A9E13641 146433FB CC939DCE 249B3EF9 + 7D2FE363 630C75D8 F681B202 AEC4617A D3DF1ED5 D5FD6561 + 2433F51F 5F066ED0 85636555 3DED1AF3 B557135E 7F57C935 + 984F0C70 E0E68B77 E2A689DA F3EFE872 1DF158A1 36ADE735 + 30ACCA4F 483A797A BC0AB182 B324FB61 D108A94B B2C8E3FB + B96ADAB7 60D7F468 1D4F42A3 DE394DF4 AE56EDE7 6372BB19 + 0B07A7C8 EE0A6D70 9E02FCE1 CDF7E2EC C03404CD 28342F61 + 9172FE9C E98583FF 8E4F1232 EEF28183 C3FE3B1B 4C6FAD73 + 3BB5FCBC 2EC22005 C58EF183 7D1683B2 C6F34A26 C1B2EFFA + 886B4238 611FCFDC DE355B3B 6519035B BC34F4DE F99C0238 + 61B46FC9 D6E6C907 7AD91D26 91F7F7EE 598CB0FA C186D91C + AEFE1309 85139270 B4130C93 BC437944 F4FD4452 E2D74DD3 + 64F2E21E 71F54BFF 5CAE82AB 9C9DF69E E86D2BC5 22363A0D + ABC52197 9B0DEADA 1DBF9A42 D5C4484E 0ABCD06B FA53DDEF + 3C1B20EE 3FD59D7C 25E41D2B 669E1EF1 6E6F52C3 164DF4FB + 7930E9E4 E58857B6 AC7D5F42 D69F6D18 7763CF1D 55034004 + 87F55BA5 7E31CC7A 7135C886 EFB4318A ED6A1E01 2D9E6832 + A907600A 918130C4 6DC778F9 71AD0038 092999A3 33CB8B7A + 1A1DB93D 7140003C 2A4ECEA9 F98D0ACC 0A8291CD CEC97DCF + 8EC9B55A 7F88A46B 4DB5A851 F44182E1 C68A007E 5E655F6A + FFFFFFFF FFFFFFFF + ''', + '6144': ''' + FFFFFFFF FFFFFFFF ADF85458 A2BB4A9A AFDC5620 273D3CF1 + D8B9C583 CE2D3695 A9E13641 146433FB CC939DCE 249B3EF9 + 7D2FE363 630C75D8 F681B202 AEC4617A D3DF1ED5 D5FD6561 + 2433F51F 5F066ED0 85636555 3DED1AF3 B557135E 7F57C935 + 984F0C70 E0E68B77 E2A689DA F3EFE872 1DF158A1 36ADE735 + 30ACCA4F 483A797A BC0AB182 B324FB61 D108A94B B2C8E3FB + B96ADAB7 60D7F468 1D4F42A3 DE394DF4 AE56EDE7 6372BB19 + 0B07A7C8 EE0A6D70 9E02FCE1 CDF7E2EC C03404CD 28342F61 + 9172FE9C E98583FF 8E4F1232 EEF28183 C3FE3B1B 4C6FAD73 + 3BB5FCBC 2EC22005 C58EF183 7D1683B2 C6F34A26 C1B2EFFA + 886B4238 611FCFDC DE355B3B 6519035B BC34F4DE F99C0238 + 61B46FC9 D6E6C907 7AD91D26 91F7F7EE 598CB0FA C186D91C + AEFE1309 85139270 B4130C93 BC437944 F4FD4452 E2D74DD3 + 64F2E21E 71F54BFF 5CAE82AB 9C9DF69E E86D2BC5 22363A0D + ABC52197 9B0DEADA 1DBF9A42 D5C4484E 0ABCD06B FA53DDEF + 3C1B20EE 3FD59D7C 25E41D2B 669E1EF1 6E6F52C3 164DF4FB + 7930E9E4 E58857B6 AC7D5F42 D69F6D18 7763CF1D 55034004 + 87F55BA5 7E31CC7A 7135C886 EFB4318A ED6A1E01 2D9E6832 + A907600A 918130C4 6DC778F9 71AD0038 092999A3 33CB8B7A + 1A1DB93D 7140003C 2A4ECEA9 F98D0ACC 0A8291CD CEC97DCF + 8EC9B55A 7F88A46B 4DB5A851 F44182E1 C68A007E 5E0DD902 + 0BFD64B6 45036C7A 4E677D2C 38532A3A 23BA4442 CAF53EA6 + 3BB45432 9B7624C8 917BDD64 B1C0FD4C B38E8C33 4C701C3A + CDAD0657 FCCFEC71 9B1F5C3E 4E46041F 388147FB 4CFDB477 + A52471F7 A9A96910 B855322E DB6340D8 A00EF092 350511E3 + 0ABEC1FF F9E3A26E 7FB29F8C 183023C3 587E38DA 0077D9B4 + 763E4E4B 94B2BBC1 94C6651E 77CAF992 EEAAC023 2A281BF6 + B3A739C1 22611682 0AE8DB58 47A67CBE F9C9091B 462D538C + D72B0374 6AE77F5E 62292C31 1562A846 505DC82D B854338A + E49F5235 C95B9117 8CCF2DD5 CACEF403 EC9D1810 C6272B04 + 5B3B71F9 DC6B80D6 3FDD4A8E 9ADB1E69 62A69526 D43161C1 + A41D570D 7938DAD4 A40E329C D0E40E65 FFFFFFFF FFFFFFFF + ''', + '8192': ''' + FFFFFFFF FFFFFFFF ADF85458 A2BB4A9A AFDC5620 273D3CF1 + D8B9C583 CE2D3695 A9E13641 146433FB CC939DCE 249B3EF9 + 7D2FE363 630C75D8 F681B202 AEC4617A D3DF1ED5 D5FD6561 + 2433F51F 5F066ED0 85636555 3DED1AF3 B557135E 7F57C935 + 984F0C70 E0E68B77 E2A689DA F3EFE872 1DF158A1 36ADE735 + 30ACCA4F 483A797A BC0AB182 B324FB61 D108A94B B2C8E3FB + B96ADAB7 60D7F468 1D4F42A3 DE394DF4 AE56EDE7 6372BB19 + 0B07A7C8 EE0A6D70 9E02FCE1 CDF7E2EC C03404CD 28342F61 + 9172FE9C E98583FF 8E4F1232 EEF28183 C3FE3B1B 4C6FAD73 + 3BB5FCBC 2EC22005 C58EF183 7D1683B2 C6F34A26 C1B2EFFA + 886B4238 611FCFDC DE355B3B 6519035B BC34F4DE F99C0238 + 61B46FC9 D6E6C907 7AD91D26 91F7F7EE 598CB0FA C186D91C + AEFE1309 85139270 B4130C93 BC437944 F4FD4452 E2D74DD3 + 64F2E21E 71F54BFF 5CAE82AB 9C9DF69E E86D2BC5 22363A0D + ABC52197 9B0DEADA 1DBF9A42 D5C4484E 0ABCD06B FA53DDEF + 3C1B20EE 3FD59D7C 25E41D2B 669E1EF1 6E6F52C3 164DF4FB + 7930E9E4 E58857B6 AC7D5F42 D69F6D18 7763CF1D 55034004 + 87F55BA5 7E31CC7A 7135C886 EFB4318A ED6A1E01 2D9E6832 + A907600A 918130C4 6DC778F9 71AD0038 092999A3 33CB8B7A + 1A1DB93D 7140003C 2A4ECEA9 F98D0ACC 0A8291CD CEC97DCF + 8EC9B55A 7F88A46B 4DB5A851 F44182E1 C68A007E 5E0DD902 + 0BFD64B6 45036C7A 4E677D2C 38532A3A 23BA4442 CAF53EA6 + 3BB45432 9B7624C8 917BDD64 B1C0FD4C B38E8C33 4C701C3A + CDAD0657 FCCFEC71 9B1F5C3E 4E46041F 388147FB 4CFDB477 + A52471F7 A9A96910 B855322E DB6340D8 A00EF092 350511E3 + 0ABEC1FF F9E3A26E 7FB29F8C 183023C3 587E38DA 0077D9B4 + 763E4E4B 94B2BBC1 94C6651E 77CAF992 EEAAC023 2A281BF6 + B3A739C1 22611682 0AE8DB58 47A67CBE F9C9091B 462D538C + D72B0374 6AE77F5E 62292C31 1562A846 505DC82D B854338A + E49F5235 C95B9117 8CCF2DD5 CACEF403 EC9D1810 C6272B04 + 5B3B71F9 DC6B80D6 3FDD4A8E 9ADB1E69 62A69526 D43161C1 + A41D570D 7938DAD4 A40E329C CFF46AAA 36AD004C F600C838 + 1E425A31 D951AE64 FDB23FCE C9509D43 687FEB69 EDD1CC5E + 0B8CC3BD F64B10EF 86B63142 A3AB8829 555B2F74 7C932665 + CB2C0F1C C01BD702 29388839 D2AF05E4 54504AC7 8B758282 + 2846C0BA 35C35F5C 59160CC0 46FD8251 541FC68C 9C86B022 + BB709987 6A460E74 51A8A931 09703FEE 1C217E6C 3826E52C + 51AA691E 0E423CFC 99E9E316 50C1217B 624816CD AD9A95F9 + D5B80194 88D9C0A0 A1FE3075 A577E231 83F81D4A 3F2FA457 + 1EFC8CE0 BA8A4FE8 B6855DFE 72B0A66E DED2FBAB FBE58A30 + FAFABE1C 5D71A87E 2F741EF8 C1FE86FE A6BBFDE5 30677F0D + 97D11D49 F7A8443D 0822E506 A9F4614E 011E2A94 838FF88C + D68C8BB7 C5C6424C FFFFFFFF FFFFFFFF + ''' + } + +# All groups from RFC 7919 use generator 2. + +g = '''02''' + +def dehexify(hexString): + ''' + Convert the "bignum" hexString + representation to a bytearray + containing the number. + ''' + return bytearray.fromhex(' '.join(line.strip() for line in hexString.splitlines())) + +def derLength(size): + ''' + Returns the ASN.1 DER length bytes + for the given size. + + Short form: For lengths <= 127, + the length is just a byte containing + the literal number. (Note that for + numbers <= 127, the MSB is not + set.) + + In doctest form, that is: + + >>> derLength(1) + bytearray(b'\\x01') + + >>> derLength(127) + bytearray(b'\\x7f') + + Long form: For lengths > 127, + the encoding is different: The + first byte has the MSB set (that + is, by itself, 0x80). The rest of + the bits in the first byte specify + the number of bytes that follow. + + So, to encode the length 128, you + would emit + + 0x81 0x80 + + The high bit of the first byte is set. + This means the remaining 7 bits contain + how many bytes follow it. If we mask the + MSB away, we end up with 0x01. So, only + a single byte follows. + The value of the following byte is 0x80, + which is 128 decimal. + + In doctest form, that is: + + >>> derLength(128) + bytearray(b'\\x81\\x80') + + Error cases: + + The size passed to this function must be an integer: + + >>> derLength(0.1) + Traceback (most recent call last): + ... + Exception: bad type + + >>> derLength('5') + Traceback (most recent call last): + ... + Exception: bad type + + Negative numbers are not supported, and throw an exception: + + >>> derLength(-1) + Traceback (most recent call last): + ... + Exception: bad size + + The long form does not support very large numbers. This is + because the 'additional bytes' counter can only count up to + 127 (2**7-1) bytes. + + So, if we try to encode a length that will use exactly 127 + bytes, it will succeed: + + >>> derLength(int('ff'*127, 16)) # doctest:+ELLIPSIS + bytearray(b'\\xff...\\xff') + + But if we try to go over that limit, we get an exception: + + >>> derLength(int('ff'*128, 16)) + Traceback (most recent call last): + ... + Exception: unencodable + ''' + + # Ensure that the passed-in size is an integer. + if not isinstance(size, (int, long)): + raise Exception('bad type') + + if size > 127: + # Convert 'size' to a hexString-style + # bignum that we can pass to dehexify. + # + # Strip '0x' prefix from the hex string. + hexString = hex(size)[2:] + # In Python 2.7, the output of hex() + # can have an L suffix. Make sure we + # strip that. + if hexString.endswith('L'): + hexString = hexString[:-1] + # Ensure the final hex string only + # contains full bytes. If not, prepend + # a zero byte. + if len(hexString) % 2 != 0: + hexString = '0' + hexString + + # If the computed hexString bignum + # contains more than 127 bytes, we + # can't encode it using ASN.1 DER + # encoding. Throw an exception. + nbytes = len(hexString) // 2 + if nbytes > 127: + raise Exception('unencodable') + + buf = dehexify(hexString) + out = bytearray((0x80 | nbytes,)) + out += buf + return out + elif size > 0: + # Short form is simply the number itself, + # as a byte. + return bytearray((size,)) + else: + # We don't support negative sizes. + raise Exception('bad size') + +def derSequence(sequence): + ''' + Encode an ASN.1 DER sequence + + Takes a sequence of DER data as its input. + + Returns a bytearray of the resulting data. + + The encoding of a DER sequence is simply + an identifier (0x30), a length (the length + of the content bytes -- see the derLength + function), and the content itself (just a + byte stream of other ASN.1 DER objects) + ''' + out = bytearray((0x30,)) # SEQUENCE tag + content = bytearray() + for entry in sequence: + content += entry + out += derLength(len(content)) + out += content + return out + +def derUnsignedInteger(hexString): + ''' + Encode a hex string to a ASN.1 DER INTEGER. + This function only handles unsigned integers. + + Returns a bytearray of the resulting data. + + The encoding of an ASN.1 DER INTEGER is an + identifier (0x02), a length (the length of the + content bytes -- see the derLength function), + and the content, which in this case is the + bytes that make up the integer. + + An INTEGER can be signed, or unsigned. Our + function here only deals with unsigned integers. + + Signed integers have the MSB/sign bit set. + + Our input data is guaranteed to be unsigned, + so if we detect that the MSB is set in the + data, we prepend a zero byte to it. This + is the way to signal that the value is unsigned + rather than signed. + ''' + out = bytearray((0x02,)) # INTEGER tag + buf = dehexify(hexString) + + # If the sign bit is set, prepend a zero byte. + # Otherwise, the number will be treated as signed, + # which we don't want. + if (buf[0] & 0x80) != 0: + buf = bytearray((0,)) + buf + out += derLength(len(buf)) + out += buf + return out + +def pem(der, kind='DH PARAMETERS'): + ''' + Convert the ASN.1 DER data to PEM form. + + Returns the resulting string (type 'unicode' for Python 2). + + The PEM format consists of a header, the content itself (base64, + using the standard alphabet) and a trailer. + + The header is of the form: + -----BEGIN $KIND----- + + and the trailer is of the form: + -----END $KIND----- + + where $KIND defines the type of data + contained in the PEM data. + + Between the header and the trailer is + the content itself. The content is the + DER form encoded using base64. + + Our implementation splits the base64 + data such that each line of base64 data + can be no longer than 64 characters long. + ''' + out = u'-----BEGIN {0}-----\n'.format(kind) + enc = base64.b64encode(der) + n = 0 + for ch in enc: + if type(ch) == int: # Python 3 + out += chr(ch) + else: + out += ch + n += 1 + if n == 64: + out += '\n' + n = 0 + if out[-1] != '\n': + out += '\n' + out += u'-----END {0}-----\n'.format(kind) + return out + +def writePEM(f, identifier, str): + f.write(str) + +def main(): + for len, str in ffdhe_str.items(): + f = codecs.open(os.path.join('output', 'dh-parameters.' + len), 'w', 'utf-8') + + writePEM(f, 'ffdhe' + len + '_pem', pem( + derSequence(( + derUnsignedInteger(str), + derUnsignedInteger(g), + )) + )) + +if __name__ == '__main__': + main() |