// Copyright 2015-2016 Brian Smith.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND AND THE AUTHORS DISCLAIM ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

// *R* and *r* in Montgomery math refer to different things, so we always use
// `R` to refer to *R* to avoid confusion, even when that's against the normal
// naming conventions. Also the standard camelCase names are used for
// `RSAKeyPair` components.
#![allow(non_snake_case)]

/// RSA signatures.

use {bits, der, error};
use untrusted;

#[cfg(feature = "rsa_signing")]
use limb;

mod padding;

// `RSA_PKCS1_SHA1` is intentionally not exposed.
#[cfg(feature = "rsa_signing")]
pub use self::padding::RSAEncoding;

pub use self::padding::{
    RSA_PKCS1_SHA256,
    RSA_PKCS1_SHA384,
    RSA_PKCS1_SHA512,

    RSA_PSS_SHA256,
    RSA_PSS_SHA384,
    RSA_PSS_SHA512
};


// Maximum RSA modulus size supported for signature verification (in bytes).
const PUBLIC_KEY_PUBLIC_MODULUS_MAX_LEN: usize = 8192 / 8;

// Keep in sync with the documentation comment for `RSAKeyPair`.
#[cfg(feature = "rsa_signing")]
const PRIVATE_KEY_PUBLIC_MODULUS_MAX_BITS: bits::BitLength =
    bits::BitLength(4096);

#[cfg(feature = "rsa_signing")]
const PRIVATE_KEY_PUBLIC_MODULUS_MAX_LIMBS: usize =
    (4096 + limb::LIMB_BITS - 1) / limb::LIMB_BITS;


/// Parameters for RSA verification.
pub struct RSAParameters {
    padding_alg: &'static padding::RSAVerification,
    min_bits: bits::BitLength,
    id: RSAParametersID,
}

#[allow(non_camel_case_types)]
enum RSAParametersID {
    RSA_PKCS1_2048_8192_SHA1,
    RSA_PKCS1_2048_8192_SHA256,
    RSA_PKCS1_2048_8192_SHA384,
    RSA_PKCS1_2048_8192_SHA512,
    RSA_PKCS1_3072_8192_SHA384,
    RSA_PSS_2048_8192_SHA256,
    RSA_PSS_2048_8192_SHA384,
    RSA_PSS_2048_8192_SHA512,
}

fn parse_public_key(input: untrusted::Input)
                    -> Result<(untrusted::Input, untrusted::Input),
                              error::Unspecified> {
    input.read_all(error::Unspecified, |input| {
        der::nested(input, der::Tag::Sequence, error::Unspecified, |input| {
            let n = der::positive_integer(input)?;
            let e = der::positive_integer(input)?;
            Ok((n, e))
        })
    })
}

fn check_public_modulus_and_exponent(
        n: bigint::Positive, e: bigint::Positive, n_min_bits: bits::BitLength,
        n_max_bits: bits::BitLength, e_min_bits: bits::BitLength)
        -> Result<(bigint::OddPositive, bigint::PublicExponent),
                  error::Unspecified> {
    // This is an incomplete implementation of NIST SP800-56Br1 Section
    // 6.4.2.2, "Partial Public-Key Validation for RSA." That spec defers to
    // NIST SP800-89 Section 5.3.3, "(Explicit) Partial Public Key Validation
    // for RSA," "with the caveat that the length of the modulus shall be a
    // length that is specified in this Recommendation." In SP800-89, two
    // different sets of steps are given, one set numbered, and one set
    // lettered. TODO: Document this in the end-user documentation for RSA
    // keys.

    // Step 3 / Step c (out of order).
    let n = n.into_odd_positive()?;
    let e = e.into_odd_positive()?;

    // `pkcs1_encode` depends on this not being small. Otherwise,
    // `pkcs1_encode` would generate padding that is invalid (too few 0xFF
    // bytes) for very small keys.
    const N_MIN_BITS: bits::BitLength = bits::BitLength(2048);

    // Step 1 / Step a. XXX: SP800-56Br1 and SP800-89 require the length of
    // the public modulus to be exactly 2048 or 3072 bits, but we are more
    // flexible to be compatible with other commonly-used crypto libraries.
    assert!(n_min_bits >= N_MIN_BITS);
    let n_bits = n.bit_length();
    let n_bits_rounded_up =
        bits::BitLength::from_usize_bytes(n_bits.as_usize_bytes_rounded_up())?;
    if n_bits_rounded_up < n_min_bits {
        return Err(error::Unspecified);
    }
    if n_bits > n_max_bits {
        return Err(error::Unspecified);
    }

    // Step 2 / Step b. NIST SP800-89 defers to FIPS 186-3, which requires
    // `e > 2**16`, so the requirement is met if and only if `e_min_bits >= 17`.
    // We enforce this when signing, but are more flexible in verification, for
    // compatibility.
    debug_assert!(e_min_bits >= bits::BitLength::from_usize_bits(2));
    let e_bits = e.bit_length();
    if e_bits < e_min_bits {
        return Err(error::Unspecified);
    }

    // Only small public exponents are supported.
    let e = e.into_public_exponent()?;

    // If `n` is less than `e` then somebody has probably accidentally swapped
    // them. The largest acceptable `e` is smaller than the smallest acceptable
    // `n`, so no additional checks need to be done.
    debug_assert!(e_min_bits < bigint::PUBLIC_EXPONENT_MAX_BITS);
    debug_assert!(bigint::PUBLIC_EXPONENT_MAX_BITS < N_MIN_BITS);

    // XXX: Steps 4 & 5 / Steps d, e, & f are not implemented. This is also the
    // case in most other commonly-used crypto libraries.

    Ok((n, e))
}

// Type-level representation of an RSA public modulus *n*. See
// `super::bigint`'s modulue-level documentation.
pub enum N {}

pub mod verification;

#[cfg(feature = "rsa_signing")]
pub mod signing;

mod bigint;

#[cfg(feature = "rsa_signing")]
mod blinding;

#[cfg(feature = "rsa_signing")]
mod random;
