package rsa // Copyright (c) 2016 Thomas Pornin // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // THIS SOFTWARE IS PROVIDED BY THE AUTHORS “AS IS” AND ANY EXPRESS OR // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE // GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import "core:bytes" import "core:crypto" import subtle "core:crypto/_subtle" import "core:encoding/endian" // Minimum size for a RSA modulus (in bits). // // Note: 1024-bits is arguably insufficient as of this writing, with // 2048-bits being a more sensible value, however 1024-bits is likely // still in frequent enough use. // // Note: CA signed TLS certificates have a strict requirement of a modulus // size that is at least 2048-bits [[ https://cabforum.org/working-groups/server/baseline-requirements/documents/]]. MODULUS_MIN_SIZE :: 1024 // Maximum size for a RSA modulus (in bits). // // This value MUST be a multiple of 64. This value MUST NOT exceed 47666 // (some computations in RSA key generation rely on the factor size being // no more than 23833 bits). RSA key sizes beyond 3072 bits don't make a // lot of sense anyway. MODULUS_MAX_SIZE :: 4096 // Maxmimum size for a RSA public exponent (in bits). // // Note: This implementation supports arbitrary size exponents, however // limit it to something sensible (some implementations are known to // choke on exponents >= 2^32), with the most common choice being // `65537`. EXPONENT_MAX_SIZE :: 32 // Maximum size for a RSA factor (in bits). This is for RSA private-key // operations. Default is to support factors up to a bit more than half // the maximum modulus size. // // This value MUST be a multiple of 32. FACTOR_MAX_SIZE :: (MODULUS_MAX_SIZE + 64) >> 1 // Default size for a RSA key (in bits). DEFAULT_MODULUS_SIZE :: 2048 // RSA public exponent used for key generation. This MUST be a prime // number greater than 2. @(private) PUBLIC_EXPONENT :: 65537 #assert(EXPONENT_MAX_SIZE <= 32) // Private_Key is a RSA private key. Private_Key :: struct { _pub_key: Public_Key, _d: Modulus, // Private exponent has the same size as n. _p: Factor, _q: Factor, // CRT coefficients. _dp: Factor, // d % (p - 1) _dq: Factor, // d % (q - 1) _iq: Factor, // q^(-1) mod p _is_initialized: bool, } // Public_Key is a RSA public key. Public_Key :: struct { _n: Modulus, _e: u32, _is_initialized: bool, } // private_key_generate uses the system entropy source to generate a new // Private_Key. The key size is specified in bits, and must be a multiple // of 8. @(require_results) private_key_generate :: proc(priv_key: ^Private_Key, key_size := DEFAULT_MODULUS_SIZE) -> bool { if !crypto.HAS_RAND_BYTES { return false } if key_size < MODULUS_MIN_SIZE || key_size > MODULUS_MAX_SIZE { return false } if key_size % 8 != 0 { return false } private_key_clear(priv_key) defer if !priv_key._is_initialized { private_key_clear(priv_key) } for { // The only way this can fail is if we get extremely unlucky // and we fail to derive `iq` (1/d mod p). if keygen_inner(priv_key, key_size) == 1 { break } } priv_key._is_initialized = true priv_key._pub_key._is_initialized = true // Self-test the key. priv_key._is_initialized = pkcs1_sig_selftest(priv_key) return priv_key._is_initialized } // private_key_n copies the private key's public modulus to dst if dst is // non-nil and of sufficient size, and returns the number of bytes // copied/would be copied (ie: calling with `dst = nil` gets the required // size). @(require_results) private_key_n :: proc(priv_key: ^Private_Key, dst: []byte) -> (n_len: int) { ensure(priv_key._is_initialized, "crypto/rsa: uninitialized private key") return public_key_n(&priv_key._pub_key, dst) } // private_key_e returns the private key's public exponent as a u32. @(require_results) private_key_e :: proc(priv_key: ^Private_Key) -> u32 { ensure(priv_key._is_initialized, "crypto/rsa: uninitialized private key") return public_key_e(&priv_key._pub_key) } // private_key_d copies the private key's private exponent `d` to dst if // dst is non-nil and of sufficient size, and returns the number of bytes // copied/would be copied (ie: calling with `dst = nil` gets the required // size). // // Note: The data returned MUST be kept confidential. @(require_results) private_key_d :: proc(priv_key: ^Private_Key, dst: []byte) -> (n_len: int) { ensure(priv_key._is_initialized, "crypto/rsa: uninitialized private key") return modulus_copyout(&priv_key._d, dst) } // private_key_p copies the private key's first prime factor `p` to dst // if dst is non-nil and of sufficient size, and returns the number of // bytes copied/would be copied (ie: calling with `dst = nil` gets the // required size). // // Note: The data returned MUST be kept confidential. @(require_results) private_key_p :: proc(priv_key: ^Private_Key, dst: []byte) -> (n_len: int) { ensure(priv_key._is_initialized, "crypto/rsa: uninitialized private key") return factor_copyout(&priv_key._p, dst) } // private_key_q copies the private key's second prime factor `q` to dst // if dst is non-nil and of sufficient size, and returns the number of // bytes copied/would be copied (ie: calling with `dst = nil` gets the // required size). // // Note: The data returned MUST be kept confidential. @(require_results) private_key_q :: proc(priv_key: ^Private_Key, dst: []byte) -> (n_len: int) { ensure(priv_key._is_initialized, "crypto/rsa: uninitialized private key") return factor_copyout(&priv_key._q, dst) } // private_key_dp copies the private key's first reduced exponent // `d % (p-1)` to dst if dst is non-nil and of sufficient size, and // returns the number of bytes copied/would be copied (ie: calling with //`dst = nil` gets the required size). // // Note: The data returned MUST be kept confidential. @(require_results) private_key_dp :: proc(priv_key: ^Private_Key, dst: []byte) -> (n_len: int) { ensure(priv_key._is_initialized, "crypto/rsa: uninitialized private key") return factor_copyout(&priv_key._dp, dst) } // private_key_dq copies the private key's second reduced exponent // `d % (q-1)` to dst if dst is non-nil and of sufficient size, and // returns the number of bytes copied/would be copied (ie: calling with //`dst = nil` gets the required size). // // Note: The data returned MUST be kept confidential. @(require_results) private_key_dq :: proc(priv_key: ^Private_Key, dst: []byte) -> (n_len: int) { ensure(priv_key._is_initialized, "crypto/rsa: uninitialized private key") return factor_copyout(&priv_key._dq, dst) } // private_key_iq copies the private key's CRT coefficient `iq` to dst if // dst is non-nil and of sufficient size, and returns the number of bytes // copied/would be copied (ie: calling with`dst = nil` gets the required // size). // // Note: The data returned MUST be kept confidential. @(require_results) private_key_iq :: proc(priv_key: ^Private_Key, dst: []byte) -> (n_len: int) { ensure(priv_key._is_initialized, "crypto/rsa: uninitialized private key") return factor_copyout(&priv_key._iq, dst) } // private_key_size returns the size of the private key's public modulus // in bytes. All ciphertexts and signatures will also be this size. @(require_results) private_key_size :: proc(priv_key: ^Private_Key) -> int { ensure(priv_key._is_initialized, "crypto/rsa: uninitialized private key") return priv_key._pub_key._n.v_len } // private_key_set_bytes sets a private key from byte-encoded components, // and returns true if and only if (⟺) the operation was successful. // // Note: All values are mandatory, and match the values included in the // PKCS private key format. // // WARNING: This routine validates that it is possible to sign/verify with // the deserialized values, however d is not checked at all, nor is the // primality of p and q. @(require_results) private_key_set_bytes :: proc( priv_key: ^Private_Key, n: []byte, e: []byte, d: []byte, p: []byte, q: []byte, dp: []byte, dq: []byte, iq: []byte, ) -> bool { private_key_clear(priv_key) defer if !priv_key._is_initialized { private_key_clear(priv_key) } if !public_key_set_bytes(&priv_key._pub_key, n, e) { return false } if !modulus_set_bytes(&priv_key._d, d) { return false } if !factor_set_bytes(&priv_key._p, p) { return false } if !factor_set_bytes(&priv_key._q, q) { return false } if !factor_set_bytes(&priv_key._dp, dp) { return false } if !factor_set_bytes(&priv_key._dq, dq) { return false } if !factor_set_bytes(&priv_key._iq, iq) { return false } priv_key._is_initialized = true // Test the key. // // Note: This DOES NOT check that p/q are prime and if d is // consistent (as it is not used by our implementation). priv_key._is_initialized = pkcs1_sig_selftest(priv_key) return priv_key._is_initialized } // private_key_set sets priv_key to src. private_key_set :: proc(priv_key, src: ^Private_Key) { if src == nil || !src._is_initialized { private_key_clear(priv_key) return } public_key_set(&priv_key._pub_key, &src._pub_key) modulus_set(&priv_key._d, &src._d) factor_set(&priv_key._p, &src._p) factor_set(&priv_key._q, &src._q) factor_set(&priv_key._dp, &src._dp) factor_set(&priv_key._dq, &src._dq) factor_set(&priv_key._iq, &src._iq) priv_key._is_initialized = true } // private_key_equal returns true if and only if (⟺) priv_key is equal to other. @(require_results) private_key_equal :: proc(priv_key, other: ^Private_Key) -> bool { ensure(priv_key._is_initialized && other._is_initialized, "crypto/rsa: uninitialized private key") pk_eq := public_key_equal(&priv_key._pub_key, &other._pub_key) eq := crypto.compare_constant_time(modulus_bytes(&priv_key._d), modulus_bytes(&other._d)) eq &= crypto.compare_constant_time(factor_bytes(&priv_key._p), factor_bytes(&other._p)) eq &= crypto.compare_constant_time(factor_bytes(&priv_key._q), factor_bytes(&other._q)) eq &= crypto.compare_constant_time(factor_bytes(&priv_key._dp), factor_bytes(&other._dp)) eq &= crypto.compare_constant_time(factor_bytes(&priv_key._dq), factor_bytes(&other._dq)) eq &= crypto.compare_constant_time(factor_bytes(&priv_key._iq), factor_bytes(&other._iq)) return pk_eq & (eq == 1) } // private_key_clear clears priv_key to the uninitialized state. private_key_clear :: proc "contextless" (priv_key: ^Private_Key) { crypto.zero_explicit(priv_key, size_of(Private_Key)) } // public_key_n copies the public key's modulus `n` to dst if dst is // non-nil and of sufficient size, and returns the number of bytes // copied/would be copied (ie: calling with `dst = nil` gets the // required size). @(require_results) public_key_n :: proc(pub_key: ^Public_Key, dst: []byte) -> (n_len: int) { ensure(pub_key._is_initialized, "crypto/rsa: uninitialized public key") return modulus_copyout(&pub_key._n, dst) } // public_key_e returns the public key's exponent `e` as a u32. @(require_results) public_key_e :: proc(pub_key: ^Public_Key) -> u32 { ensure(pub_key._is_initialized, "crypto/rsa: uninitialized public key") return pub_key._e } // public_key_size returns the size of the public key's modulus in bytes. // All ciphertexts and signatures will also be this size. @(require_results) public_key_size :: proc(pub_key: ^Public_Key) -> int { ensure(pub_key._is_initialized, "crypto/rsa: uninitialized public key") return pub_key._n.v_len } // public_key_set_bytes sets a public key from byte-encoded components, // and returns true if and only if (⟺) the operation was successful. @(require_results) public_key_set_bytes :: proc(pub_key: ^Public_Key, n, e: []byte) -> bool { public_key_clear(pub_key) defer if !pub_key._is_initialized { public_key_clear(pub_key) } ok := modulus_set_bytes(&pub_key._n, n) if !ok { return false } if modulus_len(&pub_key._n) < MODULUS_MIN_SIZE >> 3 { return false } if !modulus_is_odd(&pub_key._n) { return false } e_ := bytes.trim_left(e, []byte{0x00}) e_len := len(e_) if e_len > EXPONENT_MAX_SIZE >> 3 { return false } e_buf: [4]byte copy(e_buf[4 - e_len:], e) e_u32 := endian.unchecked_get_u32be(e_buf[:]) if e_u32 < 3 || e_u32 & 1 == 0 { return false } pub_key._e = e_u32 pub_key._is_initialized = true return true } // public_key_set sets pub_key to src. public_key_set :: proc(pub_key, src: ^Public_Key) { if src == nil || !src._is_initialized { public_key_clear(pub_key) return } modulus_set(&pub_key._n, &src._n) pub_key._e = src._e pub_key._is_initialized = true } // public_key_set_priv sets pub_key to the public component of priv_key. public_key_set_priv :: proc(pub_key: ^Public_Key, priv_key: ^Private_Key) { ensure(priv_key._is_initialized, "crypto/rsa: uninitialized private key") pub_key^ = priv_key._pub_key } // public_key_equal returns true if and only if (⟺) pub_key is equal to other. public_key_equal :: proc(pub_key, other: ^Public_Key) -> bool { ensure(pub_key._is_initialized && other._is_initialized, "crypto/rsa: uninitialized public key") eq := crypto.compare_constant_time(modulus_bytes(&pub_key._n), modulus_bytes(&other._n)) eq &= int(subtle.eq(pub_key._e, other._e)) return eq == 1 } // public_key_clear clears pub_key to the uninitialized state. public_key_clear :: proc "contextless" (pub_key: ^Public_Key) { crypto.zero_explicit(pub_key, size_of(Public_Key)) } // size returns the size of the key's public modulus in bytes. // All ciphertexts and signatures will also be this size. size :: proc "contextless" (key: ^$T) -> int where T == Private_Key || T == Private_Key { when T == Private_Key { return private_key_size(key) } else { return public_key_size(key) } }