2010-08-20 08:46:21

by Miloslav Trmac

[permalink] [raw]
Subject: [PATCH 00/19] RFC, v2: "New" /dev/crypto user-space interface

Hello,
following is a patchset providing an user-space interface to the kernel crypto
API. It is based on the older, BSD-compatible, implementation, but the
user-space interface is different.

Major changes since the previous post:
* "struct nlattr"-based extensible attributes used for extensibility
of most operations, both for input and output attributes
* algorithms (ciphers, key wrapping, key derivation) are identified using
strings in the userspace API
* Full compat_ioctl implementation
* Version number added to the data format used when wrapping keys for storage
* Patch set split into smaller parts, reordered to keep the tree buildable.
(If you want to review primarily the user-space API, see patches
1,14,15,17,18.)

The libtom* patches will probably still be too large for the mailing list;
the whole patch set is also available at
http://people.redhat.com/mitr/cryptodev-ncr/v2/ .

Original patch set description follows.

These are the major differences compared to the BSD-like interface:

* The API supports key storage and management inside the kernel.
An application can thus ask the kernel to generate a key; the key is
then referenced via an integer identifier, and the application can be
prevented from accessing the raw key data. Such a key can, if so configured,
still be wrapped for key transport to the recipient of the message, and
unwrapped by the recipient.

The kernel key storage does not span system reboots, but applications can
also wrap the keys for persistent storage, receiving an encrypted blob that
does not reveal the raw key data, but can be later loaded back into the
kernel.

* More algorithms and mechanisms are supported by the API, including public key
algorithms (RSA/DSA encryption and signing, D-H key derivation, key wrapping).

Motivations for the extensions: governments are asking for more security
features in the operating systems they procure, which make user-space
implementations impractical. A few examples:

* Advanced crypto module for OSPP for Common Criteria requires OS services
implementing several low-level crypto algorithms (e.g. AES, RSA). This
requires the separation of crypto services from the consumer of those
services. (The threat model is that apps tend to have more vulnerabilities
than libraries and compromise of the app will lead to the ability to access
key material.) An user-space library is not separated, options are a) root
running daemon that does crypto, but this would be slow due to context
switches, scheduler mismatching and all the IPC overhead and b) use crypto
that is in the kernel.

* FIPS-140-3 calls out for cryptographic functions to be non-debuggable (ptrace)
meaning that you cannot get to the key material. The solution is the same as
above.

* GPOSPP requires auditing for crypto events (so does FIPS-140 level 2 cert).
To do this you need any crypto to have CAP_AUDIT_WRITE permissions which
means making everything that links to openssl, libgcrypt, or nss setuid
root. Making firefox and 400 other applications setuid root is a non-starter.
So, the solution is again to use crypto in the kernel where auditing needs no
special permissions.

Other advantages to having kernel crypto available to user space:

* User space will be able to take advantage of kernel drivers for hardware
crypto accelerators.

* glibc, which in some configurations links to libfreebl3.so for hashes
necessary for crypt(), will be able to use the kernel implementation; this
means one less library to load and dynamically link for each such process.

The code is derived from the original cryptodev-linux patch set; most of the
new implementation was written by Nikos Mavrogiannopoulos
<[email protected]>. Attributions are included in the respective
source files.


2010-08-20 08:46:29

by Miloslav Trmac

[permalink] [raw]
Subject: [PATCH 01/19] User-space API definition

This patch introduces the new user-space API, <ncr.h>.

Quick overview:

* open("/dev/crypto") to get a FD, which acts as a namespace for key and
session identifiers.

* ioctl(NCRIO_KEY_INIT) to allocate a key object; then generate the key
material inside the kernel, load a plaintext key, unwrap a key, or
derive a key. Similarly the key material can be copied out of the
kernel or wrapped.

* ioctl(NCRIO_SESSION_INIT) to allocate a crypto session (to encrypt,
decrypt, hash, sign, or verify signature), then
ioctl(NCRIO_SESSION_UPDATE) to act on chunks of data. Deallocate the
session, and optionally retrieve session results (e.g. hash or
signature), using ioctl(NCRIO_SESSION_FINAL).

There is also NCRIO_SESSION_ONCE for an one-shot crypto operation
using a single user->kernel context switch.

Full documentation of the interface is in
Documentation/crypto/userspace.txt .
---
Documentation/crypto/userspace.txt | 510 ++++++++++++++++++++++++++++++++++++
include/linux/Kbuild | 1 +
include/linux/ncr.h | 273 +++++++++++++++++++
3 files changed, 784 insertions(+), 0 deletions(-)
create mode 100644 Documentation/crypto/userspace.txt
create mode 100644 include/linux/ncr.h

diff --git a/Documentation/crypto/userspace.txt b/Documentation/crypto/userspace.txt
new file mode 100644
index 0000000..5839fda
--- /dev/null
+++ b/Documentation/crypto/userspace.txt
@@ -0,0 +1,510 @@
+CRYPTO(4) Linux Programmer’s Manual CRYPTO(4)
+
+NAME
+ /dev/crypto - kernel cryptographic module interface
+
+SYNOPSIS
+ #include <ncr.h>
+ int fd = open("/dev/crypto", O_RDWR);
+ int res = ioctl(fd, NCRIO..., &data);
+
+DESCRIPTION
+ The /dev/crypto device file provides an ioctl(2) interface to the ker-
+ nel-space crypto implementation.
+
+ Each open(2) of the /dev/crypto file establishes a separate namespace
+ within which crypto operations work. The namespace can be shared
+ across threads and processes by sharing the open file description.
+ Last close of the open file description automatically destroys all
+ objects allocated within the namespace.
+
+ All ioctl(2)s have the same form: The user sets up a data structure
+ with input data, and passes a pointer to the data structure as the
+ third parameter to ioctl(2). On success, output data is available in
+ the same structure.
+
+OPERATION ATTRIBUTES
+ In addition to the fixed members of data structures, a process can pass
+ additional attributes on input of most operations, and receive addi-
+ tional attributes back from the kernel. If this is supported by a spe-
+ cific operation, the fixed data structure members for this operation
+ include input_size and output_size.
+
+ The input attributes immediately follow the fixed data structure as a
+ sequence of correctly aligned (struct nlattr, attribute data) pairs,
+ using the same data layout and formatting rules as netlink(7) messages.
+ The input_size member must be initialized to the total length of input
+ (including both the fixed data structure and the attributes).
+
+ There is an (unspecified) upper limit on the total size of all
+ attributes, which should be large enough to accommodate any reasonable
+ application. If a larger input is provided nevertheless, the operation
+ will fail with EOVERFLOW.
+
+ Output attributes, if any, are written by the kernel in the same format
+ following the fixed data structure (overwriting input attributes, if
+ any). The output_size member must be initialized to the total space
+ available for output (including the fixed data structure and space for
+ attributes), and is updated by the kernel with the total space actually
+ used for attributes.
+
+ If the space available for output attributes is too small, the opera-
+ tion will fail with ERANGE.
+
+ As a special case, input_size may be zero to indicate no input
+ attributes are supplied. Similarly, output_size may be zero to indi-
+ cate no space for output attributes is provided; in such case out-
+ put_size is not overwritten by the kernel with the total space actually
+ used (which is equal to size of the fixed data structure) and remains
+ zero when the operation finishes.
+
+ The kernel accepts and silently ignores unknown attributes.
+
+ The kernel will not add new output attributes to existing operations in
+ future releases unless the new output attribute was explicitly
+ requested by the application. (Therefore, the application does not
+ have to allocate any extra space for output attributes it does not
+ expect.)
+
+ The following attributes are used in more than one operation:
+
+ NCR_ATTR_ALGORITHM
+ A NUL-terminated string specifying an algorithm (to be used in
+ an operation, or as a property of a key), using the Linux crypto
+ API algorithm names.
+
+ Three additional algorithm names are recognized: rsa, dsa, dh.
+
+ NCR_ATTR_IV
+ Unformatted binary data specifying an initialization vector,
+
+ NCR_ATTR_KEY_FLAGS
+ An 32-bit unsigned integer in native byte order specifying key
+ flags, a combination of NCR_KEY_FLAG_EXPORTABLE (the key mate-
+ rial can be exported in plaintext to user space) and
+ NCR_KEY_FLAG_WRAPPABLE (the key material can be wrapped and the
+ result made available to user space).
+
+ NCR_ATTR_KEY_ID
+ Arbitrary binary data which can be used by the application for
+ key identification.
+
+ NCR_ATTR_KEY_TYPE
+ An 32-bit unsigned integer in native byte order specifying key
+ type, one of NCR_KEY_TYPE_SECRET, NCR_KEY_TYPE_PUBLIC and
+ NCR_KEY_TYPE_PRIVATE.
+
+ NCR_ATTR_WRAPPING_ALGORITHM
+ A NUL-terminated string specifying a key wrapping algorithm.
+ The values walg-aes-rfc3394 and walg-aes-rfc5649 are currently
+ supported.
+
+OPERATIONS
+ The following operations are defined:
+
+ NCRIO_KEY_INIT
+ Allocate a kernel-space key object. The third ioctl(s) parame-
+ ter is ignored (key attributes are set later, when the key mate-
+ rial is initialized). Returns an ncr_key_t descriptor for the
+ key object (valid within the current /dev/crypto namespace) on
+ success.
+
+ There is a per-process and per-user (not per-namespace) limit on
+ the number key objects that can be allocated.
+
+ NCRIO_KEY_DEINIT
+ Deallocate a kernel-space key object. The parameter points to a
+ ncr_key_t descriptor of the key object. After all other opera-
+ tions using this key object (if any) terminate, the key material
+ will be cleared and the object will be freed. Note that this
+ may happen both before this operation returns, and after it
+ returns, depending on other references to this key object.
+
+ NCRIO_KEY_GENERATE
+ Clear existing key material in the specified key object, and
+ generate new key material.
+
+ The parameter points to struct ncr_key_generate, which specifies
+ the destination key object in its key member.
+
+ The following input attributes are recognized:
+
+ NCR_ATTR_ALGORITHM
+ Mandatory.
+
+ NCR_ATTR_KEY_FLAGS
+ Optional, flags are unchanged if not present.
+
+ NCR_ATTR_SECRET_KEY_BITS
+ Mandatory for symmetric keys. An 32-bit unsigned integer
+ in native byte order specifying key length in bits.
+
+ Only symmetric keys can be currently generated using this opera-
+ tion.
+
+ In addition to generating the key material, the "persistent" key
+ ID is reset to a random value.
+
+ NCRIO_KEY_GENERATE_PAIR
+ Similar to NCRIO_KEY_GENERATE, except that a pair of public/pri-
+ vate keys is generated.
+
+ The parameter points to struct ncr_key_generate_pair, which
+ specifies the destination key objects in its private_key and
+ public_key members.
+
+ The following input attributes are recognized:
+
+ NCR_ATTR_KEY_FLAGS
+ Optional, flags are unchanged if not present.
+
+ NCR_ATTR_RSA_E
+ For RSA keys, the public exponent as a big-endian multi-
+ ple-precision integer. Optional, defaults to 65537.
+
+ NCR_ATTR_RSA_MODULUS_BITS
+ Mandatory for RSA keys. An 32-bit unsigned integer in
+ native byte order specifying modulus length in bits.
+
+ NCR_ATTR_DSA_P_BITS
+ For DSA keys, length of the "p" key parameter in bits as
+ an 32-bit unsigned integer in native byte order.
+ Optional, defaults to 1024.
+
+ NCR_ATTR_DSA_Q_BITS
+ For DSA keys, length of the "q" key parameter in bits as
+ an 32-bit unsigned integer in native byte order.
+ Optional, defaults to 160.
+
+ NCR_ATTR_DH_BASE
+ Mandatory for D-H keys. The prime modulus of a D-H group
+ as a big-endian multiple-precision integer.
+
+ NCR_ATTR_DH_PRIME
+ Mandatory for D-H keys. The generator of a D-H group as
+ a big-endian multiple-precision integer.
+
+ The NCR_KEY_FLAG_EXPORTABLE and NCR_KEY_FLAG_WRAPPABLE flags are
+ automatically set on the public key.
+
+ In addition to generating the key material, the "persistent" key
+ ID of both keys is set to a same value derived from the public
+ key.
+
+ NCRIO_KEY_DERIVE
+ Derive a new key using one key and additional data.
+
+ The parameter points to struct ncr_key_derive, which specifies
+ the source and destination keys in the input_key and new_key
+ members.
+
+ The following input attributes are recognized:
+
+ NCR_ATTR_KEY_FLAGS
+ Optional, flags are unchanged if not present.
+
+ NCR_ATTR_DERIVATION_ALGORITHM
+ Mandatory. A NUL-terminated string specifying a key
+ derivation algorithm. Only dh is currently supported.
+
+ NCR_ATTR_DH_PUBLIC
+ Mandatory for D-H derivation. The peer’s public D-H
+ value as a big-endian multiple-precision integer.
+
+ NCRIO_KEY_EXPORT
+ Export key material in the specified key object to user space.
+ Only keys with the NCR_KEY_FLAG_EXPORTABLE flag can be exported
+ using this operation.
+
+ The parameter points to struct ncr_key_export, which specifies
+ the key to export in the key member, and a buffer for the
+ exported data in the buffer and buffer_size members.
+
+ On success, size of the exported key is returned.
+
+ Symmetric keys are written directly into the destination buffer.
+ Public and private keys are formatted using ASN.1, except for DH
+ public keys, which are written a raw binary number.
+
+ NCRIO_KEY_IMPORT
+ Clear existing key material in the specified key object, and
+ import key material from user space.
+
+ The parameter points to struct ncr_key_import, which specifies
+ the destination key in the key member, and the input data in the
+ data and data_size members.
+
+ The following input attributes are recognized:
+
+ NCR_ATTR_ALGORITHM
+ Mandatory.
+
+ NCR_ATTR_KEY_FLAGS
+ Optional, flags are unchanged if not present.
+
+ NCR_ATTR_KEY_ID
+ Optional, the "persistent" key ID is unchanged if not
+ present.
+
+ NCR_ATTR_KEY_TYPE
+ Mandatory.
+
+ The data format is the same as in the NCRIO_KEY_EXPORT opera-
+ tion.
+
+ NCRIO_KEY_GET_INFO
+ Get metadata of an existing key.
+
+ The parameter points to struct ncr_key_get_info, which specifies
+ key, the key descriptor.
+
+ The following input attributes are recognized:
+
+ NCR_ATTR_WANTED_ATTRS
+ An array of unsigned 16-bit integers in native byte
+ order, specifying the set of output attributes that
+ should be returned. NCR_ATTR_ALGORITHM,
+ NCR_ATTR_KEY_FLAGS and NCR_ATTR_KEY_TYPE are currently
+ supported. Unsupported attribute requests are silently
+ ignored
+
+ The output attributes explicitly requested in
+ NCR_ATTR_WANTED_ATTRS, and no other output attributes, are
+ returned.
+
+ NCRIO_KEY_WRAP
+ Wrap one key using another, and write the result to user space.
+ Only keys with the NCR_KEY_FLAG_WRAPPABLE flag can be wrapped
+ using this operation.
+
+ The parameter points to struct ncr_key_wrap, which specifies the
+ key to wrap in the source_key member, the wrapping key in the
+ wrapping_key member, and a buffer for the wrapped data in the
+ buffer and buffer_size members.
+
+ The following input attributes are recognized:
+
+ NCR_ATTR_IV
+ Optional, an empty IV is used if not present.
+
+ NCR_ATTR_WRAPPING_ALGORITHM
+ Mandatory.
+
+ Only secret keys can be currently wrapped.
+
+ On success, size of the wrapped key is returned.
+
+ NCRIO_KEY_UNWRAP
+ Unwrap user-space data into a kernel-space key using another
+ key.
+
+ The parameter points to struct ncr_key_unwrap, which specifies
+ the destination key in the dest_key member, the wrapping key in
+ the wrapping_key member, and the wrapped data in the data and
+ data_size members.
+
+ The following input attributes are recognized:
+
+ NCR_ATTR_IV
+ Optional, an empty IV is used if not present.
+
+ NCR_ATTR_WRAPPING_ALGORITHM
+ Mandatory.
+
+ The unwrapped key will have the NCR_KEY_FLAG_WRAPPABLE flag set,
+ and the NCR_KEY_FLAG_EXPORTABLE flag clear.
+
+ NCRIO_KEY_STORAGE_WRAP
+ Wrap a key object and associated metadata using the system-wide
+ storage master key, and write the result to user space.
+
+ Only keys with the NCR_KEY_FLAG_WRAPPABLE flag can be wrapped
+ using this operation.
+
+ The parameter points to struct ncr_key_storage_wrap, which spec-
+ ifies the key to wrap in the key member, and a buffer for the
+ wrapped data in the buffer and buffer_size members.
+
+ On success, size of the wrapped key is returned.
+
+ Both symmetric and asymmetric keys can be wrapped using this
+ operation. The wrapped data includes data corresponding the
+ NCR_ATTR_ALGORITHM, NCR_ATTR_KEY_FLAGS, NCR_ATTR_KEY_TYPE and
+ NCR_ATTR_KEY_ID attributes in addition to the raw key material:
+
+ NCRIO_KEY_STORAGE_UNWRAP
+ Unwrap key and associated metadata created using NCRIO_KEY_STOR-
+ AGE_WRAP, and restore the information into a specified key
+ object.
+
+ The parameter points to struct ncr_key_storage_unwrap, which
+ specifies the destination key in the key member and the wrapped
+ data in the data and data_size members.
+
+ See NCRIO_KEY_STORAGE_WRAP above for the list of attributes that
+ will be restored.
+
+ NCRIO_SESSION_INIT
+ Allocate a session for performing crypto operations.
+
+ The parameter points to struct ncr_session_init, which specifies
+ the operation to perform, one of NCR_OP_ENCRYPT, NCR_OP_DECRYPT,
+ NCR_OP_SIGN and NCR_OP_VERIFY, in the op member. Use
+ NCR_OP_SIGN for computing an unkeyed hash as well as keyed
+ hashes and signatures.
+
+ The following input attributes are recognized:
+
+ NCR_ATTR_ALGORITHM
+ Mandatory.
+
+ NCR_ATTR_IV
+ Mandatory for some operations and algorithms.
+
+ NCR_ATTR_KEY
+ Mandatory for some operations and algorithms. An 32-bit
+ unsigned integer in native byte order specifying the key
+ to use for the operation.
+
+ NCR_ATTR_RSA_ENCODING_METHOD
+ Mandatory for RSA. An 32-bit unsigned integer in native
+ byte order specifying a RSA encoding method, one of
+ RSA_PKCS1_V1_5, RSA_PKCS1_OAEP and RSA_PKCS1_PSS.
+
+ NCR_ATTR_RSA_OAEP_HASH_ALGORITHM
+ Mandatory for RSA with RSA_PKCS1_OAEP. A NUL-terminated
+ string specifying a hash algorithm used in the OAEP
+ encoding method.
+
+ NCR_ATTR_RSA_PSS_SALT_LENGTH
+ For RSA with RSA_PKCS1_PSS. An 32-bit unsigned integer
+ in native byte order specifying the PSS salt length.
+ Optional, defaults to 0.
+
+ NCR_ATTR_SIGNATURE_HASH_ALGORITHM
+ Mandatory for some operations and algorithms. A NUL-ter-
+ minated string specifying a hash algorithm underlying a
+ signature, using the same formats as NCR_ATTR_ALGORITHM.
+
+ On success, an integer descriptor for the created session (valid
+ within the current /dev/crypto namespace) is returned.
+
+ NCRIO_SESSION_UPDATE
+ Update an existing crypto session with new data (for operations,
+ such as hashing, for which data can be supplied in pieces), or
+ perform a single operation using the session context (for opera-
+ tions, such as public key encryption, that work on separate
+ units of data).
+
+ The parameter points to struct ncr_session_update, which speci-
+ fies the descriptor of the session in the ses member.
+
+ The following input attributes are recognized:
+
+ NCR_ATTR_UPDATE_INPUT_DATA
+ A struct ncr_session_input_data specifying input for the
+ operation in its data and data_size members.
+
+ NCR_ATTR_UPDATE_INPUT_KEY_AS_DATA
+ An 32-bit unsigned integer in native byte order specify-
+ ing the key descriptor serving as input for the opera-
+ tion. This can be currently used only to compute or ver-
+ ify a signature or hash of a symmetric key: the keying
+ material is directly used as input data for the underly-
+ ing hash.
+
+ NCR_ATTR_UPDATE_OUTPUT_BUFFER
+ Mandatory for some operations and algorithms. A struct
+ ncr_session_output_buffer specifying buffer for operation
+ output in its buffer and buffer_size members. On success
+ the size of output is written to the variable pointed to
+ by the result_size_ptr member.
+
+ It is mandatory to include one of the NCR_ATTR_UPDATE_INPUT_DATA
+ and NCR_ATTR_UPDATE_INPUT_KEY_AS_DATA attributes.
+
+ For the NCR_OP_ENCRYPT and NCR_OP_DECRYPT operations using sym-
+ metric ciphers, the operation is performed on the input data,
+ resulting in an output data block of the same size; for opera-
+ tions using public-key cryptography, a single operation is per-
+ formed on the input data, resulting in output data.
+
+ For the NCR_OP_SIGN and NCR_OP_VERIFY operations, the input data
+ is supplied to the underlying hash function; no output data is
+ produced.
+
+ NCRIO_SESSION_FINAL
+ Finalize an existing crypto session and deallocate it.
+
+ The parameter points to struct ncr_session_final, which speci-
+ fies the descriptor of the session in the ses member.
+
+ If one of the NCR_ATTR_UPDATE_INPUT_DATA and
+ NCR_ATTR_UPDATE_INPUT_KEY_AS_DATA attributes is present, all
+ attributes are first processed as if using NCRIO_SESSION_UPDATE;
+ thus, the last update operation can be performed together with
+ the finalization in one step.
+
+ The following input attributes are recognized:
+
+ NCR_ATTR_FINAL_INPUT_DATA
+ Mandatory for some operations and algorithms. A struct
+ ncr_session_input_data as described above, specifying
+ input for the operation.
+
+ NCR_ATTR_FINAL_OUTPUT_BUFFER
+ Mandatory for some operations and algorithms. A struct
+ ncr_session_output_buffer as described above, specifying
+ buffer for operation output.
+
+ There is no specific finalization operation performed for
+ NCR_OP_ENCRYPT and NCR_OP_DECRYPT.
+
+ For the NCR_OP_SIGN operation, the signature is created and
+ written as output data.
+
+ For the NCR_OP_VERIFY operation, a signature specified as input
+ is verified and the result of this operation is returned: non-
+ zero for a valid signature, zero for an invalid signature. Note
+ that the ioctl(2) operation return value will be non-negative,
+ i.e. "success", even if the signature verification fails, as
+ long all inputs were specified correctly.
+
+ The session will be deallocated even if the NCRIO_SESSION_FINAL
+ operation reports an error, as long as a valid session descrip-
+ tor was specified.
+
+ NCRIO_SESSION_ONCE
+ Perform an one-shot crypto operation, allocating a temporary
+ session, supplying a single instance of data, and finalizing the
+ session in one operation.
+
+ The parameter points to struct ncr_session_once, which specifies
+ the operation to perform in the op member.
+
+ The attributes handled as if by passing to a NCRIO_SESSION_INIT
+ operation followed by a NCRIO_SESSION_FINAL operation, and the
+ return value of the NCRIO_SESSION_FINAL is returned on success.
+
+ NCRIO_MASTER_KEY_SET
+ Set the system-wide storage master key. Only a process with
+ EUID 0 and the CAP_SYS_ADMIN capability is allowed to perform
+ this operation. Once a master key is set, it can be changed
+ only by rebooting the system and setting a different key.
+
+ The parameter points to struct ncr_master_key_set, which speci-
+ fies the key material in user space using the key and key_size
+ members.
+
+ Only an AES key with size 16, 24, or 32 bytes is currently
+ acceptable.
+
+CONFIGURATION
+ The NCRIO_KEY_STORAGE_WRAP and NCRIO_KEY_STORAGE_UNWRAP ioctl()s work
+ only after a storage master key is configured by the system administra-
+ tor. See NCRIO_MASTER_KEY_SET above.
+
+FILES
+ /dev/crypto
+
+Linux 2010-08-20 CRYPTO(4)
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 756f831..41790cd 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -116,6 +116,7 @@ header-y += mmtimer.h
header-y += mqueue.h
header-y += mtio.h
header-y += ncp_no.h
+header-y += ncr.h
header-y += neighbour.h
header-y += net_dropmon.h
header-y += net_tstamp.h
diff --git a/include/linux/ncr.h b/include/linux/ncr.h
new file mode 100644
index 0000000..c288cb8
--- /dev/null
+++ b/include/linux/ncr.h
@@ -0,0 +1,273 @@
+#ifndef _LINUX_NCR_H
+#define _LINUX_NCR_H
+
+#include <linux/types.h>
+
+/* Serves to make sure the structure is suitably aligned to continue with
+ a struct nlattr without external padding.
+
+ 4 is NLA_ALIGNTO from <linux/netlink.h>, but if we
+ included <linux/netlink.h>, the user would have to include <sys/socket.h>
+ as well for no obvious reason. "4" is fixed by ABI. */
+#define __NL_ATTRIBUTES char __align[] __attribute__((aligned(4)))
+
+/* In all ioctls, input_size specifies size of the ncr_* structure and the
+ following attributes.
+
+ output_size specifies space available for returning output, including the
+ initial ncr_* structure, and is updated by the ioctl() with the space
+ actually used.
+
+ There are two special cases: input_size 0 means not attributes are supplied,
+ and is treated equivalent to sizeof(struct ncr_*). output_size 0 means no
+ space for output attributes is available, and is not updated. */
+
+/* FIXME: better names for algorithm parameters? */
+/* FIXME: Split key generation/derivation attributes to decrease the number
+ of attributes used for the frequent operations? */
+enum {
+ NCR_ATTR_UNSPEC, /* 0 is special in lib/nlattr.c. */
+ NCR_ATTR_ALGORITHM, /* NLA_NUL_STRING */
+ NCR_ATTR_DERIVATION_ALGORITHM, /* NLA_NUL_STRING - NCR_DERIVE_* */
+ NCR_ATTR_SIGNATURE_HASH_ALGORITHM, /* NLA_NUL_STRING */
+ NCR_ATTR_WRAPPING_ALGORITHM, /* NLA_NUL_STRING - NCR_WALG_* */
+ NCR_ATTR_UPDATE_INPUT_DATA, /* NLA_BINARY - ncr_session_input_data */
+ /* NLA_BINARY - ncr_session_output_buffer */
+ NCR_ATTR_UPDATE_OUTPUT_BUFFER,
+ NCR_ATTR_UPDATE_INPUT_KEY_AS_DATA, /* NLA_U32 - ncr_key_t */
+ NCR_ATTR_FINAL_INPUT_DATA, /* NLA_BINARY - ncr_session_input_data */
+ /* NLA_BINARY - ncr_session_output_buffer */
+ NCR_ATTR_FINAL_OUTPUT_BUFFER,
+ NCR_ATTR_KEY, /* NLA_U32 - ncr_key_t */
+ NCR_ATTR_KEY_FLAGS, /* NLA_U32 - NCR_KEY_FLAG_* */
+ NCR_ATTR_KEY_ID, /* NLA_BINARY */
+ NCR_ATTR_KEY_TYPE, /* NLA_U32 - ncr_key_type_t */
+ NCR_ATTR_IV, /* NLA_BINARY */
+ NCR_ATTR_SECRET_KEY_BITS, /* NLA_U32 */
+ NCR_ATTR_RSA_MODULUS_BITS, /* NLA_U32 */
+ NCR_ATTR_RSA_E, /* NLA_BINARY */
+ NCR_ATTR_RSA_ENCODING_METHOD, /* NLA_U32 - ncr_rsa_type_t */
+ NCR_ATTR_RSA_OAEP_HASH_ALGORITHM, /* NLA_NUL_STRING */
+ NCR_ATTR_RSA_PSS_SALT_LENGTH, /* NLA_U32 */
+ NCR_ATTR_DSA_P_BITS, /* NLA_U32 */
+ NCR_ATTR_DSA_Q_BITS, /* NLA_U32 */
+ NCR_ATTR_DH_PRIME, /* NLA_BINARY */
+ NCR_ATTR_DH_BASE, /* NLA_BINARY */
+ NCR_ATTR_DH_PUBLIC, /* NLA_BINARY */
+ NCR_ATTR_WANTED_ATTRS, /* NLA_BINARY - array of u16 IDs */
+
+ /* Add new attributes here */
+
+ NCR_ATTR_END__,
+ NCR_ATTR_MAX = NCR_ATTR_END__ - 1
+};
+
+#define NCR_CIPHER_MAX_BLOCK_LEN 32
+#define NCR_HASH_MAX_OUTPUT_SIZE 64
+
+#define NCR_WALG_AES_RFC3394 "walg-aes-rfc3394" /* for secret keys only */
+#define NCR_WALG_AES_RFC5649 "walg-aes-rfc5649" /* can wrap arbitrary key */
+
+typedef enum {
+ NCR_KEY_TYPE_INVALID,
+ NCR_KEY_TYPE_SECRET=1,
+ NCR_KEY_TYPE_PUBLIC=2,
+ NCR_KEY_TYPE_PRIVATE=3,
+} ncr_key_type_t;
+
+/* Key handling
+ */
+
+typedef __s32 ncr_key_t;
+
+#define NCR_KEY_INVALID ((ncr_key_t)-1)
+
+#define NCR_KEY_FLAG_EXPORTABLE 1
+#define NCR_KEY_FLAG_WRAPPABLE (1<<1)
+/* when generating a pair the flags correspond to private
+ * and public key usage is implicit. For example when private
+ * key can decrypt then public key can encrypt. If private key
+ * can sign then public key can verify.
+ */
+#define NCR_KEY_FLAG_DECRYPT (1<<2)
+#define NCR_KEY_FLAG_SIGN (1<<3)
+
+struct ncr_key_generate {
+ __u32 input_size, output_size;
+ ncr_key_t key;
+ __NL_ATTRIBUTES;
+};
+
+struct ncr_key_generate_pair {
+ __u32 input_size, output_size;
+ ncr_key_t private_key;
+ ncr_key_t public_key;
+ __NL_ATTRIBUTES;
+};
+
+typedef enum {
+ RSA_PKCS1_V1_5, /* both signatures and encryption */
+ RSA_PKCS1_OAEP, /* for encryption only */
+ RSA_PKCS1_PSS, /* for signatures only */
+} ncr_rsa_type_t;
+
+#define NCR_DERIVE_DH "dh"
+
+
+struct ncr_key_derive {
+ __u32 input_size, output_size;
+ ncr_key_t input_key;
+ ncr_key_t new_key;
+ __NL_ATTRIBUTES;
+};
+
+#define MAX_KEY_ID_SIZE 20
+
+struct ncr_key_get_info {
+ __u32 input_size, output_size;
+ ncr_key_t key;
+ __NL_ATTRIBUTES;
+};
+
+struct ncr_key_import {
+ __u32 input_size, output_size;
+ ncr_key_t key;
+ const void __user *data;
+ __u32 data_size;
+ __NL_ATTRIBUTES;
+};
+
+struct ncr_key_export {
+ __u32 input_size, output_size;
+ ncr_key_t key;
+ void __user *buffer;
+ int buffer_size;
+ __NL_ATTRIBUTES;
+};
+
+#define NCRIO_KEY_INIT _IO('c', 204)
+/* generate a secret key */
+#define NCRIO_KEY_GENERATE _IOWR('c', 205, struct ncr_key_generate)
+/* generate a public key pair */
+#define NCRIO_KEY_GENERATE_PAIR _IOWR('c', 206, struct ncr_key_generate_pair)
+/* derive a new key from an old one */
+#define NCRIO_KEY_DERIVE _IOWR('c', 207, struct ncr_key_derive)
+/* return information on a key */
+#define NCRIO_KEY_GET_INFO _IOWR('c', 208, struct ncr_key_get_info)
+/* export a secret key */
+#define NCRIO_KEY_EXPORT _IOWR('c', 209, struct ncr_key_export)
+/* import a secret key */
+#define NCRIO_KEY_IMPORT _IOWR('c', 210, struct ncr_key_import)
+
+#define NCRIO_KEY_DEINIT _IOR ('c', 215, ncr_key_t)
+
+/* Key wrap ioctls
+ */
+struct ncr_key_wrap {
+ __u32 input_size, output_size;
+ ncr_key_t wrapping_key;
+ ncr_key_t source_key;
+ void __user *buffer;
+ int buffer_size;
+ __NL_ATTRIBUTES;
+};
+
+struct ncr_key_unwrap {
+ __u32 input_size, output_size;
+ ncr_key_t wrapping_key;
+ ncr_key_t dest_key;
+ const void __user *data;
+ __u32 data_size;
+ __NL_ATTRIBUTES;
+};
+
+#define NCRIO_KEY_WRAP _IOWR('c', 250, struct ncr_key_wrap)
+#define NCRIO_KEY_UNWRAP _IOWR('c', 251, struct ncr_key_unwrap)
+
+/* Internal ops */
+struct ncr_master_key_set {
+ __u32 input_size, output_size;
+ const void __user *key;
+ __u32 key_size;
+ __NL_ATTRIBUTES;
+};
+
+#define NCRIO_MASTER_KEY_SET _IOWR('c', 260, struct ncr_master_key_set)
+
+/* These are similar to key_wrap and unwrap except that will store some extra
+ * fields to be able to recover a key */
+struct ncr_key_storage_wrap {
+ __u32 input_size, output_size;
+ ncr_key_t key;
+ void __user *buffer;
+ int buffer_size;
+ __NL_ATTRIBUTES;
+};
+
+struct ncr_key_storage_unwrap {
+ __u32 input_size, output_size;
+ ncr_key_t key;
+ const void __user *data;
+ __u32 data_size;
+ __NL_ATTRIBUTES;
+};
+
+#define NCRIO_KEY_STORAGE_WRAP _IOWR('c', 261, struct ncr_key_storage_wrap)
+#define NCRIO_KEY_STORAGE_UNWRAP _IOWR('c', 262, struct ncr_key_storage_wrap)
+
+/* Crypto Operations ioctls
+ */
+
+typedef enum {
+ NCR_OP_ENCRYPT=1,
+ NCR_OP_DECRYPT,
+ NCR_OP_SIGN,
+ NCR_OP_VERIFY,
+} ncr_crypto_op_t;
+
+typedef __s32 ncr_session_t;
+#define NCR_SESSION_INVALID ((ncr_session_t)-1)
+
+struct ncr_session_input_data {
+ const void __user *data;
+ __kernel_size_t data_size;
+};
+
+struct ncr_session_output_buffer {
+ void __user *buffer;
+ __kernel_size_t buffer_size;
+ __kernel_size_t __user *result_size_ptr;
+};
+
+struct ncr_session_init {
+ __u32 input_size, output_size;
+ __u32 op; /* ncr_crypto_op_t */
+ __NL_ATTRIBUTES;
+};
+
+struct ncr_session_update {
+ __u32 input_size, output_size;
+ ncr_session_t ses;
+ __NL_ATTRIBUTES;
+};
+
+struct ncr_session_final {
+ __u32 input_size, output_size;
+ ncr_session_t ses;
+ __NL_ATTRIBUTES;
+};
+
+struct ncr_session_once {
+ __u32 input_size, output_size;
+ ncr_crypto_op_t op;
+ __NL_ATTRIBUTES;
+};
+
+#define NCRIO_SESSION_INIT _IOWR('c', 300, struct ncr_session_init)
+#define NCRIO_SESSION_UPDATE _IOWR('c', 301, struct ncr_session_update)
+#define NCRIO_SESSION_FINAL _IOWR('c', 302, struct ncr_session_final)
+
+/* everything in one call */
+#define NCRIO_SESSION_ONCE _IOWR('c', 303, struct ncr_session_once)
+
+#endif
--
1.7.2.1

2010-08-20 08:46:30

by Miloslav Trmac

[permalink] [raw]
Subject: [PATCH 02/19] Add CRYPTO_USERSPACE config option

---
crypto/Kconfig | 5 +++++
crypto/Makefile | 2 ++
crypto/userspace/Makefile | 1 +
3 files changed, 8 insertions(+), 0 deletions(-)
create mode 100644 crypto/userspace/Makefile

diff --git a/crypto/Kconfig b/crypto/Kconfig
index 81c185a..022768a 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -31,6 +31,11 @@ config CRYPTO_FIPS
this is. Note that CRYPTO_ANSI_CPRNG is requred if this
option is selected

+config CRYPTO_USERSPACE
+ tristate "User-space crypto API"
+ help
+ This option provides an user-space API for cryptographic operations.
+
config CRYPTO_ALGAPI
tristate
select CRYPTO_ALGAPI2
diff --git a/crypto/Makefile b/crypto/Makefile
index 9e8f619..d284dff 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -90,3 +90,5 @@ obj-$(CONFIG_CRYPTO_GHASH) += ghash-generic.o
#
obj-$(CONFIG_XOR_BLOCKS) += xor.o
obj-$(CONFIG_ASYNC_CORE) += async_tx/
+
+obj-$(CONFIG_CRYPTO_USERSPACE) += userspace/
diff --git a/crypto/userspace/Makefile b/crypto/userspace/Makefile
new file mode 100644
index 0000000..b607b90
--- /dev/null
+++ b/crypto/userspace/Makefile
@@ -0,0 +1 @@
+ccflags-y += -I$(src)/libtommath -I$(src)/libtomcrypt/headers -I$(src) -DLTC_SOURCE
--
1.7.2.1

2010-08-20 08:46:37

by Miloslav Trmac

[permalink] [raw]
Subject: [PATCH 05/19] Add internal /dev/crypto implementation headers

That's it, .c files will finally follow in the next patch.
---
crypto/userspace/cryptodev_int.h | 82 +++++++++++++
crypto/userspace/ncr-dh.h | 25 ++++
crypto/userspace/ncr-int.h | 245 ++++++++++++++++++++++++++++++++++++++
crypto/userspace/ncr-pk.h | 55 +++++++++
4 files changed, 407 insertions(+), 0 deletions(-)
create mode 100644 crypto/userspace/cryptodev_int.h
create mode 100644 crypto/userspace/ncr-dh.h
create mode 100644 crypto/userspace/ncr-int.h
create mode 100644 crypto/userspace/ncr-pk.h

diff --git a/crypto/userspace/cryptodev_int.h b/crypto/userspace/cryptodev_int.h
new file mode 100644
index 0000000..6754427
--- /dev/null
+++ b/crypto/userspace/cryptodev_int.h
@@ -0,0 +1,82 @@
+/* cipher stuff */
+#ifndef CRYPTODEV_INT_H
+# define CRYPTODEV_INT_H
+
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/fdtable.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/ncr.h>
+#include <linux/scatterlist.h>
+
+#define PFX "cryptodev: "
+#define dprintk(level,severity,format,a...) \
+ do { \
+ if (level <= cryptodev_verbosity) \
+ printk(severity PFX "%s[%u]: " format, \
+ current->comm, current->pid, \
+ ##a); \
+ } while (0)
+
+extern int cryptodev_verbosity;
+
+/* For zero copy */
+int __get_userbuf(uint8_t __user *addr, uint32_t len, int write,
+ int pgcount, struct page **pg, struct scatterlist *sg);
+void release_user_pages(struct page **pg, int pagecount);
+
+/* last page - first page + 1 */
+#define PAGECOUNT(buf, buflen) \
+ ((((unsigned long)(buf + buflen - 1) & PAGE_MASK) >> PAGE_SHIFT) - \
+ (((unsigned long) buf & PAGE_MASK) >> PAGE_SHIFT) + 1)
+
+#define DEFAULT_PREALLOC_PAGES 32
+
+struct cipher_data
+{
+ int init; /* 0 uninitialized */
+ int blocksize;
+ int ivsize;
+ struct {
+ struct crypto_ablkcipher* s;
+ struct cryptodev_result *result;
+ struct ablkcipher_request *request;
+ uint8_t iv[NCR_CIPHER_MAX_BLOCK_LEN];
+ } async;
+};
+
+int cryptodev_cipher_init(struct cipher_data* out, const char* alg_name, uint8_t * key, size_t keylen);
+void cryptodev_cipher_deinit(struct cipher_data* cdata);
+ssize_t cryptodev_cipher_decrypt( struct cipher_data* cdata, const struct scatterlist *sg1, struct scatterlist *sg2, size_t len);
+ssize_t cryptodev_cipher_encrypt( struct cipher_data* cdata, const struct scatterlist *sg1, struct scatterlist *sg2, size_t len);
+
+void cryptodev_cipher_set_iv(struct cipher_data* cdata, void* iv, size_t iv_size);
+int _cryptodev_cipher_decrypt(struct cipher_data* cdata, const void* ciphertext,
+ size_t ciphertext_size, void* plaintext, size_t plaintext_size);
+int _cryptodev_cipher_encrypt(struct cipher_data* cdata, const void* plaintext,
+ size_t plaintext_size, void* ciphertext, size_t ciphertext_size);
+
+/* hash stuff */
+struct hash_data
+{
+ int init; /* 0 uninitialized */
+ int digestsize;
+ struct {
+ struct crypto_ahash *s;
+ struct cryptodev_result *result;
+ struct ahash_request *request;
+ } async;
+};
+
+int cryptodev_hash_final( struct hash_data* hdata, void* output);
+ssize_t cryptodev_hash_update( struct hash_data* hdata, struct scatterlist *sg, size_t len);
+ssize_t _cryptodev_hash_update( struct hash_data* hdata, const void* data, size_t len);
+int cryptodev_hash_reset( struct hash_data* hdata);
+void cryptodev_hash_deinit(struct hash_data* hdata);
+int cryptodev_hash_init( struct hash_data* hdata, const char* alg_name, int hmac_mode, void* mackey, size_t mackeylen);
+
+#endif /* CRYPTODEV_INT_H */
diff --git a/crypto/userspace/ncr-dh.h b/crypto/userspace/ncr-dh.h
new file mode 100644
index 0000000..cc45d32
--- /dev/null
+++ b/crypto/userspace/ncr-dh.h
@@ -0,0 +1,25 @@
+#ifndef NCR_DH_H
+# define NCR_DH_H
+
+#include <tomcrypt.h>
+
+typedef struct {
+ int type; /* PK_PRIVATE or PK_PUBLIC */
+ mp_int p;
+ mp_int g;
+ mp_int x; /* private */
+ mp_int y; /* public: y=g^x */
+} dh_key;
+
+int dh_generate_key(dh_key * key);
+int dh_import_params(dh_key * key, uint8_t* p, size_t p_size, uint8_t* g, size_t g_size);
+void dh_free(dh_key * key);
+int dh_generate_public(dh_key * public, dh_key* private);
+
+int dh_export(uint8_t *out, unsigned long *outlen, int type, dh_key *key);
+int dh_import(const uint8_t *in, size_t inlen, dh_key *key);
+
+int dh_derive_gxy(struct key_item_st* newkey, dh_key * key,
+ void* pk, size_t pk_size);
+
+#endif
diff --git a/crypto/userspace/ncr-int.h b/crypto/userspace/ncr-int.h
new file mode 100644
index 0000000..c7e1dfb
--- /dev/null
+++ b/crypto/userspace/ncr-int.h
@@ -0,0 +1,245 @@
+#ifndef NCR_INT_H
+# define NCR_INT_H
+
+#include <linux/compat.h>
+#include <linux/idr.h>
+#include <linux/mutex.h>
+#include <linux/ncr.h>
+#include <asm/atomic.h>
+#include "cryptodev_int.h"
+#include <ncr-pk.h>
+#include <ncr-dh.h>
+
+#define KEY_DATA_MAX_SIZE 3*1024
+#define NCR_CIPHER_MAX_KEY_LEN 1024
+
+#define err() printk(KERN_DEBUG"ncr: %s: %s: %d\n", __FILE__, __func__, __LINE__)
+
+struct nlattr;
+struct ncr_out;
+
+// Not all known algorithms - only for quick internal identification
+enum ncr_algorithm {
+ NCR_ALG_NONE__,
+ NCR_ALG_NULL,
+
+ NCR_ALG_MD5,
+ NCR_ALG_SHA1,
+ NCR_ALG_SHA2_224,
+ NCR_ALG_SHA2_256,
+ NCR_ALG_SHA2_384,
+ NCR_ALG_SHA2_512,
+
+ NCR_ALG_RSA,
+ NCR_ALG_DSA,
+ NCR_ALG_DH,
+};
+
+struct algo_properties_st {
+ enum ncr_algorithm algo;
+ const char *kstr;
+ size_t kstr_len;
+ unsigned needs_iv:1;
+ unsigned is_hmac:1;
+ unsigned can_sign:1;
+ unsigned can_digest:1;
+ unsigned can_encrypt:1;
+ unsigned can_kx:1; /* key exchange */
+ unsigned is_symmetric:1;
+ unsigned is_pk:1;
+ int digest_size;
+ /* NCR_KEY_TYPE_SECRET if for a secret key algorithm or MAC,
+ * NCR_KEY_TYPE_PUBLIC for a public key algorithm.
+ */
+ ncr_key_type_t key_type;
+};
+
+struct session_item_st {
+ const struct algo_properties_st *algorithm;
+ ncr_crypto_op_t op;
+
+ /* contexts for various options.
+ * simpler to have them like that than
+ * in a union.
+ */
+ struct cipher_data cipher;
+ struct ncr_pk_ctx pk;
+ struct hash_data hash;
+
+ struct scatterlist *sg;
+ struct page **pages;
+ unsigned array_size;
+ unsigned available_pages;
+ struct mutex mem_mutex; /* down when the
+ * values above are changed.
+ */
+
+ struct key_item_st* key;
+
+ atomic_t refcnt;
+ ncr_session_t desc;
+};
+
+struct key_item_st {
+ /* This object is also not protected from concurrent access.
+ */
+ ncr_key_type_t type;
+ unsigned int flags;
+ const struct algo_properties_st *algorithm; /* non-NULL for public/private keys */
+ uint8_t key_id[MAX_KEY_ID_SIZE];
+ size_t key_id_size;
+
+ union {
+ struct {
+ uint8_t data[NCR_CIPHER_MAX_KEY_LEN];
+ size_t size;
+ } secret;
+ union {
+ rsa_key rsa;
+ dsa_key dsa;
+ dh_key dh;
+ } pk;
+ } key;
+
+ atomic_t refcnt;
+ atomic_t writer;
+
+ /* owner. The one charged with this */
+ uid_t uid;
+ pid_t pid;
+
+ int context_id; /* Only for auditing */
+ ncr_key_t desc;
+};
+
+/* all the data associated with the open descriptor
+ * are here.
+ */
+struct ncr_lists {
+ int id; /* Used only for auditing */
+
+ struct mutex key_idr_mutex;
+ struct idr key_idr;
+
+ /* sessions */
+ struct mutex session_idr_mutex;
+ struct idr session_idr;
+};
+
+struct ncr_lists *ncr_init_lists(void);
+void ncr_deinit_lists(struct ncr_lists *lst);
+
+int ncr_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg);
+long ncr_compat_ioctl(struct ncr_lists *lst, unsigned int cmd,
+ unsigned long arg);
+
+/* key derivation */
+int ncr_key_derive(struct ncr_lists *lst, const struct ncr_key_derive *data,
+ struct nlattr *tb[]);
+
+/* key handling */
+int ncr_key_init(struct ncr_lists *lst);
+int ncr_key_deinit(struct ncr_lists *lst, ncr_key_t desc);
+int ncr_key_export(struct ncr_lists *lst, const struct ncr_key_export *data,
+ struct nlattr *tb[]);
+int ncr_key_import(struct ncr_lists *lst, const struct ncr_key_import *data,
+ struct nlattr *tb[]);
+void ncr_key_list_deinit(struct ncr_lists *lst);
+int ncr_key_generate(struct ncr_lists *lst, const struct ncr_key_generate *gen,
+ struct nlattr *tb[]);
+int ncr_key_get_info(struct ncr_lists *lst, struct ncr_out *out,
+ const struct ncr_key_get_info *info, struct nlattr *tb[]);
+
+int ncr_key_generate_pair(struct ncr_lists *lst,
+ const struct ncr_key_generate_pair *gen,
+ struct nlattr *tb[]);
+int ncr_key_get_public(struct ncr_lists *lst, void __user* arg);
+
+int ncr_key_item_get_read(struct key_item_st**st, struct ncr_lists *lst,
+ ncr_key_t desc);
+/* get key item for writing */
+int ncr_key_item_get_write( struct key_item_st** st,
+ struct ncr_lists *lst, ncr_key_t desc);
+void _ncr_key_item_put( struct key_item_st* item);
+
+typedef enum {
+ LIMIT_TYPE_KEY,
+ NUM_LIMIT_TYPES
+} limits_type_t;
+
+void ncr_limits_remove(uid_t uid, pid_t pid, limits_type_t type);
+int ncr_limits_add_and_check(uid_t uid, pid_t pid, limits_type_t type);
+void ncr_limits_init(void);
+void ncr_limits_deinit(void);
+
+int ncr_key_wrap(struct ncr_lists *lst, const struct ncr_key_wrap *wrap,
+ struct nlattr *tb[]);
+int ncr_key_unwrap(struct ncr_lists *lst, const struct ncr_key_unwrap *wrap,
+ struct nlattr *tb[]);
+int ncr_key_storage_wrap(struct ncr_lists *lst,
+ const struct ncr_key_storage_wrap *wrap,
+ struct nlattr *tb[]);
+int ncr_key_storage_unwrap(struct ncr_lists *lst,
+ const struct ncr_key_storage_unwrap *wrap,
+ struct nlattr *tb[]);
+
+/* sessions */
+struct session_item_st* ncr_session_new(struct ncr_lists *lst);
+void _ncr_sessions_item_put( struct session_item_st* item);
+struct session_item_st* ncr_sessions_item_get(struct ncr_lists *lst, ncr_session_t desc);
+void ncr_sessions_list_deinit(struct ncr_lists *lst);
+
+int ncr_session_init(struct ncr_lists *lists,
+ const struct ncr_session_init *session,
+ struct nlattr *tb[]);
+int ncr_session_update(struct ncr_lists *lists,
+ const struct ncr_session_update *op, struct nlattr *tb[],
+ int compat);
+int ncr_session_final(struct ncr_lists *lists,
+ const struct ncr_session_final *op, struct nlattr *tb[],
+ int compat);
+int ncr_session_once(struct ncr_lists *lists,
+ const struct ncr_session_once *once, struct nlattr *tb[],
+ int compat);
+
+/* master key */
+extern struct key_item_st master_key;
+
+void ncr_master_key_reset(void);
+
+/* storage */
+int key_from_storage_data(struct key_item_st* key, const void* data, size_t data_size);
+int key_to_storage_data( uint8_t** data, size_t * data_size, const struct key_item_st *key);
+
+
+/* misc helper macros */
+
+const struct algo_properties_st *_ncr_algo_to_properties(const char *algo);
+const struct algo_properties_st *_ncr_nla_to_properties(const struct nlattr *nla);
+const char *ncr_algorithm_name(const struct algo_properties_st *algo);
+
+/* CONFIG_COMPAT handling */
+
+#ifdef CONFIG_COMPAT
+struct compat_ncr_session_input_data {
+ compat_uptr_t data;
+ compat_size_t data_size;
+};
+
+struct compat_ncr_session_output_buffer {
+ compat_uptr_t buffer;
+ compat_size_t buffer_size;
+ compat_uptr_t result_size_ptr;
+};
+#endif
+
+int ncr_session_input_data_from_nla(struct ncr_session_input_data *dest,
+ const struct nlattr *nla, int compat);
+
+int ncr_session_output_buffer_from_nla(struct ncr_session_output_buffer *dest,
+ const struct nlattr *nla, int compat);
+
+int ncr_session_output_buffer_set_size(const struct ncr_session_output_buffer *dest,
+ size_t size, int compat);
+
+#endif
diff --git a/crypto/userspace/ncr-pk.h b/crypto/userspace/ncr-pk.h
new file mode 100644
index 0000000..412caf5
--- /dev/null
+++ b/crypto/userspace/ncr-pk.h
@@ -0,0 +1,55 @@
+#ifndef NCR_PK_H
+# define NCR_PK_H
+
+#include <tomcrypt.h>
+
+struct nlattr;
+
+struct ncr_pk_ctx {
+ const struct algo_properties_st *algorithm; /* algorithm */
+
+ const struct algo_properties_st *sign_hash; /* for verification */
+
+ const struct algo_properties_st *oaep_hash;
+ int salt_len; /* for RSA-PSS signatures */
+
+ int type; /* libtomcrypt type */
+ int init; /* non zero if initialized */
+
+ struct key_item_st * key;
+};
+
+/* PK */
+void ncr_pk_clear(struct key_item_st* key);
+int ncr_pk_generate(const struct algo_properties_st *algo, struct nlattr *tb[],
+ struct key_item_st* private, struct key_item_st* public);
+int ncr_pk_pack( const struct key_item_st * key, uint8_t * packed, uint32_t * packed_size);
+int ncr_pk_unpack( struct key_item_st * key, const void * packed, size_t packed_size);
+
+/* encryption/decryption */
+int ncr_pk_cipher_init(const struct algo_properties_st *algo,
+ struct ncr_pk_ctx* ctx, struct nlattr *tb[],
+ struct key_item_st *key,
+ const struct algo_properties_st *sign_hash);
+void ncr_pk_cipher_deinit(struct ncr_pk_ctx* ctx);
+
+int ncr_pk_cipher_encrypt(const struct ncr_pk_ctx* ctx,
+ const struct scatterlist* isg, unsigned int isg_cnt, size_t isg_size,
+ struct scatterlist *osg, unsigned int osg_cnt, size_t* osg_size);
+
+int ncr_pk_cipher_decrypt(const struct ncr_pk_ctx* ctx,
+ const struct scatterlist* isg, unsigned int isg_cnt, size_t isg_size,
+ struct scatterlist *osg, unsigned int osg_cnt, size_t* osg_size);
+
+int ncr_pk_cipher_sign(const struct ncr_pk_ctx *ctx, const void *hash,
+ size_t hash_size, void *sig, size_t *sig_size);
+
+int ncr_pk_cipher_verify(const struct ncr_pk_ctx* ctx, const void *sig,
+ size_t sig_size, const void *hash, size_t hash_size);
+
+int _ncr_tomerr(int err);
+
+int ncr_pk_derive(struct key_item_st* newkey, struct key_item_st* oldkey,
+ struct nlattr *tb[]);
+
+#endif
--
1.7.2.1

2010-08-20 08:45:49

by Miloslav Trmac

[permalink] [raw]
Subject: [PATCH 06/19] Add ioctl() argument and attribute handling utils

Main entry points:

NCR_GET_INPUT_ARGS:
Read a fixed struct and any attached attributes from userspace

NCR_GET_INPUT_ARGS_NO_OUTPUT:
Same as above, and inform the users the kernel will attach no
additional attributes.

NCR_OUT_INIT/ncr_out_free:
Allocate and free a context that allows operation handlers to
return attributes to userspace.

ncr_out_finish:
Write the attributes from the context to userspace. Split like
this so that only NCR_OUT_INIT (in future "ncr.c") deals with
the raw ioctl() argument, but the specific operation can use
this call to detect errors and perhaps clean up.

ncr_out_*:
Add attributes to the context.
---
crypto/userspace/Makefile | 5 +
crypto/userspace/utils.c | 297 +++++++++++++++++++++++++++++++++++++++++++++
crypto/userspace/utils.h | 98 +++++++++++++++
3 files changed, 400 insertions(+), 0 deletions(-)
create mode 100644 crypto/userspace/utils.c
create mode 100644 crypto/userspace/utils.h

diff --git a/crypto/userspace/Makefile b/crypto/userspace/Makefile
index b607b90..f7f3ea2 100644
--- a/crypto/userspace/Makefile
+++ b/crypto/userspace/Makefile
@@ -1 +1,6 @@
ccflags-y += -I$(src)/libtommath -I$(src)/libtomcrypt/headers -I$(src) -DLTC_SOURCE
+
+cryptodev-objs := utils.o
+
+
+obj-$(CONFIG_CRYPTO_USERSPACE) += cryptodev.o
diff --git a/crypto/userspace/utils.c b/crypto/userspace/utils.c
new file mode 100644
index 0000000..514833c
--- /dev/null
+++ b/crypto/userspace/utils.c
@@ -0,0 +1,297 @@
+/*
+ * New driver for /dev/crypto device (aka CryptoDev)
+ *
+ * Copyright (c) 2010 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ *
+ * Red Hat Author: Miloslav Trmač
+ *
+ */
+
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <net/netlink.h>
+#include "ncr-int.h"
+#include "utils.h"
+
+#ifdef CONFIG_COMPAT
+/* max() is too clever for compile-time constants */
+#define CONST_MAX(A, B) ((A) > (B) ? (A) : (B))
+
+#define MAX_SESSION_INPUT_DATA_SIZE \
+ (CONST_MAX(sizeof(struct ncr_session_input_data), \
+ sizeof(struct compat_ncr_session_input_data)))
+#define MAX_SESSION_OUTPUT_BUFFER_SIZE \
+ (CONST_MAX(sizeof(struct ncr_session_output_buffer), \
+ sizeof(struct compat_ncr_session_output_buffer)))
+
+#else /* !CONFIG_COMPAT */
+
+#define MAX_SESSION_INPUT_DATA_SIZE (sizeof(struct ncr_session_input_data))
+#define MAX_SESSION_OUTPUT_BUFFER_SIZE \
+ (sizeof(struct ncr_session_output_buffer))
+
+#endif /* !CONFIG_COMPAT */
+
+static const struct nla_policy ncr_attr_policy[NCR_ATTR_MAX + 1] = {
+ [NCR_ATTR_ALGORITHM] = { NLA_NUL_STRING, 0 },
+ [NCR_ATTR_DERIVATION_ALGORITHM] = { NLA_NUL_STRING, 0 },
+ [NCR_ATTR_SIGNATURE_HASH_ALGORITHM] = { NLA_NUL_STRING, 0 },
+ [NCR_ATTR_WRAPPING_ALGORITHM] = { NLA_NUL_STRING, 0 },
+ [NCR_ATTR_UPDATE_INPUT_DATA] = {
+ NLA_BINARY, MAX_SESSION_INPUT_DATA_SIZE
+ },
+ [NCR_ATTR_UPDATE_OUTPUT_BUFFER] = {
+ NLA_BINARY, MAX_SESSION_OUTPUT_BUFFER_SIZE
+ },
+ [NCR_ATTR_UPDATE_INPUT_KEY_AS_DATA] = { NLA_U32, 0 },
+ [NCR_ATTR_FINAL_INPUT_DATA] = {
+ NLA_BINARY, MAX_SESSION_INPUT_DATA_SIZE
+ },
+ [NCR_ATTR_FINAL_OUTPUT_BUFFER] = {
+ NLA_BINARY, MAX_SESSION_OUTPUT_BUFFER_SIZE
+ },
+ [NCR_ATTR_KEY] = { NLA_U32, 0 },
+ [NCR_ATTR_KEY_FLAGS] = { NLA_U32, 0 },
+ [NCR_ATTR_KEY_ID] = { NLA_BINARY, 0 },
+ [NCR_ATTR_KEY_TYPE] = { NLA_U32, 0 },
+ [NCR_ATTR_IV] = { NLA_BINARY, 0 },
+ [NCR_ATTR_SECRET_KEY_BITS] = { NLA_U32, 0 },
+ [NCR_ATTR_RSA_MODULUS_BITS] = { NLA_U32, 0 },
+ [NCR_ATTR_RSA_E] = { NLA_BINARY, 0 },
+ [NCR_ATTR_RSA_ENCODING_METHOD] = { NLA_U32, 0 },
+ [NCR_ATTR_RSA_OAEP_HASH_ALGORITHM] = { NLA_NUL_STRING, 0 },
+ [NCR_ATTR_RSA_PSS_SALT_LENGTH] = { NLA_U32, 0 },
+ [NCR_ATTR_DSA_P_BITS] = { NLA_U32, 0 },
+ [NCR_ATTR_DSA_Q_BITS] = { NLA_U32, 0 },
+ [NCR_ATTR_DH_PRIME] = { NLA_BINARY, 0 },
+ [NCR_ATTR_DH_BASE] = { NLA_BINARY, 0 },
+ [NCR_ATTR_DH_PUBLIC] = { NLA_BINARY, 0 },
+ [NCR_ATTR_WANTED_ATTRS] = { NLA_BINARY, 0 },
+};
+
+void *__ncr_get_input_args(void *fixed, struct nlattr *tb[], size_t fixed_size,
+ u32 *input_size_ptr, const void __user *arg)
+{
+ size_t input_size, buf_size;
+ void *buf;
+ int ret;
+
+ if (unlikely(copy_from_user(fixed, arg, fixed_size))) {
+ err();
+ return ERR_PTR(-EFAULT);
+ }
+ input_size = *input_size_ptr;
+
+ /* NCR_GET_INPUT_ARGS/NCR_GET_INPUT_ARGS_NO_OUTPUT has verified
+ fixed_size is correctly aligned for a struct nlattr. */
+ if (input_size == 0)
+ input_size = fixed_size;
+ else if (unlikely(input_size < fixed_size)) {
+ err();
+ return ERR_PTR(-EINVAL);
+ }
+ buf_size = input_size - fixed_size;
+ if (unlikely(buf_size > NCR_MAX_ATTR_SIZE)) {
+ err();
+ return ERR_PTR(-EOVERFLOW);
+ }
+
+ if (buf_size == 0)
+ buf = NULL;
+ else {
+ const char __user *var_arg;
+
+ buf = kmalloc(buf_size, GFP_KERNEL);
+ if (unlikely(buf == NULL)) {
+ err();
+ return ERR_PTR(-ENOMEM);
+ }
+ var_arg = (const char __user *)arg + fixed_size;
+ if (unlikely(copy_from_user(buf, var_arg, buf_size))) {
+ err();
+ ret = -EFAULT;
+ goto err_buf;
+ }
+ }
+
+ ret = nla_parse(tb, NCR_ATTR_MAX, buf, buf_size, ncr_attr_policy);
+ if (ret != 0) {
+ err();
+ goto err_buf;
+ }
+
+ return buf;
+
+err_buf:
+ kfree(buf);
+ return ERR_PTR(ret);
+}
+
+static int update_output_size(void __user *arg, size_t output_size_offset,
+ u32 old_value, u32 new_value)
+{
+ if (old_value != 0 && old_value != new_value) {
+ u32 __user *dest;
+
+ dest = (u32 __user *)((char __user *)arg + output_size_offset);
+ return put_user(new_value, dest);
+ }
+ return 0;
+}
+
+void *__ncr_get_input_args_no_output(void *fixed, struct nlattr *tb[],
+ size_t fixed_size, u32 *input_size_ptr,
+ size_t output_size_offset,
+ void __user *arg)
+{
+ void *attr_buf;
+ u32 output_size;
+ int ret;
+
+ attr_buf = __ncr_get_input_args(fixed, tb, fixed_size, input_size_ptr,
+ arg);
+ if (IS_ERR(attr_buf))
+ return attr_buf;
+
+ output_size = *(const u32 *)((const char *)fixed + output_size_offset);
+ ret = update_output_size(arg, output_size_offset, output_size,
+ fixed_size);
+ if (ret != 0) {
+ kfree(attr_buf);
+ return ERR_PTR(ret);
+ }
+ return attr_buf;
+}
+
+int __ncr_out_init(struct ncr_out *out, const void *fixed, size_t fixed_size,
+ size_t output_size_offset, void __user *arg)
+{
+ u32 output_size;
+
+ /* NCR_OUT_INIT has verified fixed_size is correctly aligned for a
+ struct nlattr. */
+ output_size = *(const u32 *)((const char *)fixed + output_size_offset);
+ if (output_size == 0)
+ out->left = 0;
+ else {
+ /* NCR_OUT_INIT has verified fixed_size is correctly aligned for
+ a struct nlattr. */
+ if (output_size < fixed_size)
+ return -EINVAL;
+ out->left = min_t(size_t, output_size - fixed_size,
+ NCR_MAX_ATTR_SIZE);
+ }
+ out->buf = kmalloc(out->left, GFP_KERNEL);
+ if (out->buf == NULL)
+ return -ENOMEM;
+ out->p = out->buf;
+ out->arg = arg;
+ out->output_size_offset = output_size_offset;
+ out->fixed_size = fixed_size;
+ out->orig_output_size = output_size;
+ return 0;
+}
+
+int ncr_out_finish(struct ncr_out *out)
+{
+ size_t buf_size;
+
+ buf_size = (char *)out->p - (char *)out->buf;
+ if (buf_size != 0) {
+ if (unlikely(copy_to_user((char __user *)out->arg
+ + out->fixed_size,
+ out->buf, buf_size)))
+ return -EFAULT;
+ }
+
+ return update_output_size(out->arg, out->output_size_offset,
+ out->orig_output_size,
+ out->fixed_size + buf_size);
+}
+
+void ncr_out_free(struct ncr_out *out)
+{
+ kfree(out->buf);
+}
+
+struct nlattr *ncr_out_reserve(struct ncr_out *out, int attrtype, int attrlen)
+{
+ size_t needed;
+ struct nlattr *nla;
+
+ needed = nla_total_size(attrlen);
+ if (out->left < needed)
+ ERR_PTR(-ERANGE);
+ nla = out->p;
+ out->p = (char *)out->p + needed;
+ out->left -= needed;
+
+ nla->nla_len = nla_attr_size(attrlen);
+ nla->nla_type = attrtype;
+ memset((unsigned char *)nla + nla->nla_len, 0, nla_padlen(attrlen));
+ return nla;
+}
+
+int ncr_out_put(struct ncr_out *out, int attrtype, int attrlen, const void *data)
+{
+ struct nlattr *nla;
+
+ nla = ncr_out_reserve(out, attrtype, attrlen);
+ if (IS_ERR(nla))
+ return PTR_ERR(nla);
+ memcpy(nla_data(nla), data, attrlen);
+ return 0;
+}
+
+/**
+ * Initialize a nlattr with @attrtype as a buffer of maximum possible size in
+ * @out. The buffer must be finalized using ncr_out_commit_buffer.
+ */
+struct nlattr *ncr_out_begin_buffer(struct ncr_out *out, int attrtype)
+{
+ struct nlattr *nla;
+
+ if (out->left < NLA_HDRLEN)
+ return ERR_PTR(-ERANGE);
+ nla = out->p;
+
+ /* Ensure the rounding down of out->left does not decrease it below
+ NLA_HDRLEN. */
+ BUILD_BUG_ON(NLA_ALIGN(NLA_HDRLEN) != NLA_HDRLEN);
+ nla->nla_len = out->left & ~(NLA_ALIGNTO - 1);
+ nla->nla_type = attrtype;
+ return nla;
+}
+
+/**
+ * Set the length of buffer initialied in @out with ncr_out_begin_buffer() to
+ * @attrlen and allow adding more attributes.
+ */
+void ncr_out_commit_buffer(struct ncr_out *out, int attrlen)
+{
+ struct nlattr *nla;
+ size_t total;
+
+ nla = out->p;
+ nla->nla_len = nla_attr_size(attrlen);
+ memset((unsigned char *)nla + nla->nla_len, 0, nla_padlen(attrlen));
+ total = nla_total_size(attrlen);
+
+ out->p = (char *)out->p + total;
+ out->left -= total;
+}
diff --git a/crypto/userspace/utils.h b/crypto/userspace/utils.h
new file mode 100644
index 0000000..2802afa
--- /dev/null
+++ b/crypto/userspace/utils.h
@@ -0,0 +1,98 @@
+#ifndef NCR_UTILS_H
+#define NCR_UTILS_H
+
+#include <linux/kernel.h>
+#include <linux/netlink.h>
+
+#define NCR_MAX_ATTR_SIZE 4096
+
+struct nlattr;
+
+struct ncr_out {
+ void *buf, *p;
+ size_t left;
+ void __user *arg;
+ size_t output_size_offset, fixed_size;
+ u32 orig_output_size;
+};
+
+#define __NCR_VERIFY_FIXED_SIZE(fixed) \
+ (BUILD_BUG_ON(sizeof(*(fixed)) != NLA_ALIGN(sizeof(*(fixed)))))
+#define __NCR_VERIFY_TB(tb) (BUILD_BUG_ON(ARRAY_SIZE(tb) != NCR_ATTR_MAX + 1))
+
+extern u32 __ncr_u32_type_check;
+#define __OUT_SIZE_OFF(fixed) \
+ ((void)(&(fixed)->output_size == &__ncr_u32_type_check), \
+ (char *)&(fixed)->output_size - (char *)(fixed))
+
+
+/**
+ * Load *@fixed and a sequence of netlink-like attributes from @arg. @fixed
+ * contains "input_size", which is an u32 filled with total input size,
+ * including the attributes, which are parsed into @tb.
+ */
+#define NCR_GET_INPUT_ARGS(fixed, tb, arg) \
+ (__NCR_VERIFY_FIXED_SIZE(fixed), \
+ __NCR_VERIFY_TB(tb), \
+ __ncr_get_input_args(fixed, tb, sizeof(*(fixed)), \
+ &(fixed)->input_size, arg))
+void *__ncr_get_input_args(void *fixed, struct nlattr *tb[], size_t fixed_size,
+ u32 *input_size_ptr, const void __user *arg);
+
+/**
+ * Load *@fixed and a sequence of netlink-like attributes from @arg. @fixed
+ * contains "input_size", which is an u32 filled with total input size,
+ * including the attributes, which are parsed into @tb. In addition, indicate
+ * to the user through u32 "output_size" that no output attributes will be
+ * returned.
+ */
+#define NCR_GET_INPUT_ARGS_NO_OUTPUT(fixed, tb, arg) \
+ (__NCR_VERIFY_FIXED_SIZE(fixed), \
+ __NCR_VERIFY_TB(tb), \
+ __ncr_get_input_args_no_output(fixed, tb, sizeof(*(fixed)), \
+ &(fixed)->input_size, \
+ __OUT_SIZE_OFF(fixed), arg))
+void *__ncr_get_input_args_no_output(void *fixed, struct nlattr *tb[],
+ size_t fixed_size, u32 *input_size_ptr,
+ size_t output_size_offset,
+ void __user *arg);
+
+/**
+ * Return a new output attribute context for attributes of *@fixed. @fixed
+ * contains "output_size", an u32 containing total output size, including
+ * @fixed. Store @arg for later ncr_out_finish().
+ */
+#define NCR_OUT_INIT(out, fixed, arg) \
+ (__NCR_VERIFY_FIXED_SIZE(fixed), \
+ __ncr_out_init((out), (fixed), sizeof(*(fixed)), \
+ __OUT_SIZE_OFF(fixed), (arg)))
+int __ncr_out_init(struct ncr_out *out, const void *fixed, size_t fixed_size,
+ size_t output_size_offset, void __user *arg);
+
+/**
+ * Write attributes from @out to user space and update user-space output_size.
+ */
+int ncr_out_finish(struct ncr_out *out);
+
+void ncr_out_free(struct ncr_out *out);
+
+int ncr_out_put(struct ncr_out *out, int attrtype, int attrlen,
+ const void *data);
+
+static inline int ncr_out_put_u32(struct ncr_out *out, int attrtype, u32 value)
+{
+ return ncr_out_put(out, attrtype, sizeof(value), &value);
+}
+
+static inline int ncr_out_put_string(struct ncr_out *out, int attrtype,
+ const char *value)
+{
+ return ncr_out_put(out, attrtype, strlen(value) + 1, value);
+}
+
+struct nlattr *ncr_out_reserve(struct ncr_out *out, int attrtype, int attrlen);
+
+struct nlattr *ncr_out_begin_buffer(struct ncr_out *out, int attrtype);
+void ncr_out_commit_buffer(struct ncr_out *out, int attrlen);
+
+#endif
--
1.7.2.1

2010-08-20 08:46:03

by Miloslav Trmac

[permalink] [raw]
Subject: [PATCH 19/19] Finally, add the /dev/crypto device.

---
crypto/userspace/cryptodev_main.c | 130 +++++++++++++++++++++++++++++++++++++
1 files changed, 130 insertions(+), 0 deletions(-)

diff --git a/crypto/userspace/cryptodev_main.c b/crypto/userspace/cryptodev_main.c
index a6712db..6ba9bd6 100644
--- a/crypto/userspace/cryptodev_main.c
+++ b/crypto/userspace/cryptodev_main.c
@@ -98,3 +98,133 @@ int __get_userbuf(uint8_t __user *addr, uint32_t len, int write,
return 0;
}

+/* ====== /dev/crypto ====== */
+
+static int
+cryptodev_open(struct inode *inode, struct file *filp)
+{
+ struct ncr_lists *ncr;
+ int ret;
+
+ ncr = ncr_init_lists();
+ if (ncr == NULL) {
+ return -ENOMEM;
+ }
+
+ ret = audit_log_crypto_op(AUDIT_CRYPTO_OP_CONTEXT_NEW, ncr->id, -1,
+ NULL, NULL, -1, NULL, 0, -1, NULL, 0);
+ if (ret < 0) {
+ ncr_deinit_lists(ncr);
+ return ret;
+ }
+
+ filp->private_data = ncr;
+ return 0;
+}
+
+static int
+cryptodev_release(struct inode *inode, struct file *filp)
+{
+ struct ncr_lists *ncr = filp->private_data;
+
+ if (ncr) {
+ audit_log_crypto_op(AUDIT_CRYPTO_OP_CONTEXT_DEL, ncr->id, -1,
+ NULL, NULL, -1, NULL, 0, -1, NULL, 0);
+ ncr_deinit_lists(ncr);
+ filp->private_data = NULL;
+ }
+
+ return 0;
+}
+
+static int
+cryptodev_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ void *ncr = filp->private_data;
+
+ if (unlikely(!ncr))
+ BUG();
+
+ return ncr_ioctl(ncr, cmd, arg);
+}
+
+/* compatibility code for 32bit userlands */
+#ifdef CONFIG_COMPAT
+
+static long
+cryptodev_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ void *ncr = file->private_data;
+
+ if (unlikely(!ncr))
+ BUG();
+
+ return ncr_compat_ioctl(ncr, cmd, arg);
+}
+
+#endif /* CONFIG_COMPAT */
+
+static const struct file_operations cryptodev_fops = {
+ .owner = THIS_MODULE,
+ .open = cryptodev_open,
+ .release = cryptodev_release,
+ .ioctl = cryptodev_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = cryptodev_compat_ioctl,
+#endif /* CONFIG_COMPAT */
+};
+
+static struct miscdevice cryptodev = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "crypto",
+ .fops = &cryptodev_fops,
+};
+
+static int __init
+cryptodev_register(void)
+{
+ int rc;
+
+ ncr_limits_init();
+ ncr_master_key_reset();
+
+ rc = misc_register (&cryptodev);
+ if (unlikely(rc)) {
+ ncr_limits_deinit();
+ printk(KERN_ERR PFX "registration of /dev/crypto failed\n");
+ return rc;
+ }
+
+ return 0;
+}
+
+static void __exit
+cryptodev_deregister(void)
+{
+ misc_deregister(&cryptodev);
+ ncr_limits_deinit();
+}
+
+/* ====== Module init/exit ====== */
+static int __init init_cryptodev(void)
+{
+ int rc;
+
+ rc = cryptodev_register();
+ if (unlikely(rc))
+ return rc;
+
+ printk(KERN_INFO PFX "driver loaded.\n");
+
+ return 0;
+}
+
+static void __exit exit_cryptodev(void)
+{
+ cryptodev_deregister();
+ printk(KERN_INFO PFX "driver unloaded.\n");
+}
+
+module_init(init_cryptodev);
+module_exit(exit_cryptodev);
--
1.7.2.1

2010-08-20 08:45:47

by Miloslav Trmac

[permalink] [raw]
Subject: [PATCH 04/19] Add libtomcrypt headers

Same as the previous patch - the header file dependencies do not allow
otherwise.

(Reviewing this in detail is probably premature, we are considering
replacing the implementation by something based on libgcrypt, which is
more actively maintained and has been probably more thorouhgly examined
for vulnerabilities.)
---
crypto/userspace/libtomcrypt/headers/tomcrypt.h | 82 ++++
.../libtomcrypt/headers/tomcrypt_argchk.h | 36 ++
.../userspace/libtomcrypt/headers/tomcrypt_cfg.h | 135 +++++++
.../libtomcrypt/headers/tomcrypt_custom.h | 408 +++++++++++++++++++
.../userspace/libtomcrypt/headers/tomcrypt_hash.h | 14 +
.../libtomcrypt/headers/tomcrypt_macros.h | 424 ++++++++++++++++++++
.../userspace/libtomcrypt/headers/tomcrypt_math.h | 13 +
.../userspace/libtomcrypt/headers/tomcrypt_misc.h | 23 +
crypto/userspace/libtomcrypt/headers/tomcrypt_pk.h | 359 +++++++++++++++++
.../userspace/libtomcrypt/headers/tomcrypt_pkcs.h | 67 +++
10 files changed, 1561 insertions(+), 0 deletions(-)
create mode 100644 crypto/userspace/libtomcrypt/headers/tomcrypt.h
create mode 100644 crypto/userspace/libtomcrypt/headers/tomcrypt_argchk.h
create mode 100644 crypto/userspace/libtomcrypt/headers/tomcrypt_cfg.h
create mode 100644 crypto/userspace/libtomcrypt/headers/tomcrypt_custom.h
create mode 100644 crypto/userspace/libtomcrypt/headers/tomcrypt_hash.h
create mode 100644 crypto/userspace/libtomcrypt/headers/tomcrypt_macros.h
create mode 100644 crypto/userspace/libtomcrypt/headers/tomcrypt_math.h
create mode 100644 crypto/userspace/libtomcrypt/headers/tomcrypt_misc.h
create mode 100644 crypto/userspace/libtomcrypt/headers/tomcrypt_pk.h
create mode 100644 crypto/userspace/libtomcrypt/headers/tomcrypt_pkcs.h

diff --git a/crypto/userspace/libtomcrypt/headers/tomcrypt.h b/crypto/userspace/libtomcrypt/headers/tomcrypt.h
new file mode 100644
index 0000000..51fe804
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/headers/tomcrypt.h
@@ -0,0 +1,82 @@
+#ifndef TOMCRYPT_H_
+#define TOMCRYPT_H_
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/nls.h>
+
+/* use configuration data */
+#include <tomcrypt_custom.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* version */
+#define CRYPT 0x0117
+#define SCRYPT "1.17"
+
+/* max size of either a cipher/hash block or symmetric key [largest of the two] */
+#define MAXBLOCKSIZE 128
+
+/* descriptor table size */
+#define TAB_SIZE 32
+
+/* error codes [will be expanded in future releases] */
+enum {
+ CRYPT_OK=0, /* Result OK */
+ CRYPT_ERROR, /* Generic Error */
+ CRYPT_NOP, /* Not a failure but no operation was performed */
+
+ CRYPT_INVALID_KEYSIZE, /* Invalid key size given */
+ CRYPT_INVALID_ROUNDS, /* Invalid number of rounds */
+ CRYPT_FAIL_TESTVECTOR, /* Algorithm failed test vectors */
+
+ CRYPT_BUFFER_OVERFLOW, /* Not enough space for output */
+ CRYPT_INVALID_PACKET, /* Invalid input packet given */
+
+ CRYPT_INVALID_PRNGSIZE, /* Invalid number of bits for a PRNG */
+ CRYPT_ERROR_READPRNG, /* Could not read enough from PRNG */
+
+ CRYPT_INVALID_CIPHER, /* Invalid cipher specified */
+ CRYPT_INVALID_HASH, /* Invalid hash specified */
+ CRYPT_INVALID_PRNG, /* Invalid PRNG specified */
+
+ CRYPT_MEM, /* Out of memory */
+
+ CRYPT_PK_TYPE_MISMATCH, /* Not equivalent types of PK keys */
+ CRYPT_PK_NOT_PRIVATE, /* Requires a private PK key */
+
+ CRYPT_INVALID_ARG, /* Generic invalid argument */
+ CRYPT_FILE_NOTFOUND, /* File Not Found */
+
+ CRYPT_PK_INVALID_TYPE, /* Invalid type of PK key */
+ CRYPT_PK_INVALID_SYSTEM,/* Invalid PK system specified */
+ CRYPT_PK_DUP, /* Duplicate key already in key ring */
+ CRYPT_PK_NOT_FOUND, /* Key not found in keyring */
+ CRYPT_PK_INVALID_SIZE, /* Invalid size input for PK parameters */
+
+ CRYPT_INVALID_PRIME_SIZE,/* Invalid size of prime requested */
+ CRYPT_PK_INVALID_PADDING /* Invalid padding on input */
+};
+
+#include <tomcrypt_cfg.h>
+#include <tomcrypt_macros.h>
+#include <tomcrypt_math.h>
+#include <tomcrypt_pk.h>
+#include <tomcrypt_hash.h>
+#include <tomcrypt_misc.h>
+#include <tomcrypt_argchk.h>
+#include <tomcrypt_pkcs.h>
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* TOMCRYPT_H_ */
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt.h,v $ */
+/* $Revision: 1.21 $ */
+/* $Date: 2006/12/16 19:34:05 $ */
diff --git a/crypto/userspace/libtomcrypt/headers/tomcrypt_argchk.h b/crypto/userspace/libtomcrypt/headers/tomcrypt_argchk.h
new file mode 100644
index 0000000..1b94434
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/headers/tomcrypt_argchk.h
@@ -0,0 +1,36 @@
+/* Defines the LTC_ARGCHK macro used within the library */
+/* ARGTYPE is defined in mycrypt_cfg.h */
+#if ARGTYPE == 0
+
+/* this is the default LibTomCrypt macro */
+void crypt_argchk(char *v, char *s, int d);
+#define LTC_ARGCHK(x) if (!(x)) { crypt_argchk(#x, __FILE__, __LINE__); }
+#define LTC_ARGCHKVD(x) LTC_ARGCHK(x)
+
+#elif ARGTYPE == 1
+
+/* fatal type of error */
+#define LTC_ARGCHK(x) assert((x))
+#define LTC_ARGCHKVD(x) LTC_ARGCHK(x)
+
+#elif ARGTYPE == 2
+
+#define LTC_ARGCHK(x) if (!(x)) { fprintf(stderr, "\nwarning: ARGCHK failed at %s:%d\n", __FILE__, __LINE__); }
+#define LTC_ARGCHKVD(x) LTC_ARGCHK(x)
+
+#elif ARGTYPE == 3
+
+#define LTC_ARGCHK(x)
+#define LTC_ARGCHKVD(x) LTC_ARGCHK(x)
+
+#elif ARGTYPE == 4
+
+#define LTC_ARGCHK(x) if (!(x)) return CRYPT_INVALID_ARG;
+#define LTC_ARGCHKVD(x) if (!(x)) return;
+
+#endif
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_argchk.h,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/08/27 20:50:21 $ */
diff --git a/crypto/userspace/libtomcrypt/headers/tomcrypt_cfg.h b/crypto/userspace/libtomcrypt/headers/tomcrypt_cfg.h
new file mode 100644
index 0000000..b750c8b
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/headers/tomcrypt_cfg.h
@@ -0,0 +1,135 @@
+/* This is the build config file.
+ *
+ * With this you can setup what to inlcude/exclude automatically during any build. Just comment
+ * out the line that #define's the word for the thing you want to remove. phew!
+ */
+
+#ifndef TOMCRYPT_CFG_H
+#define TOMCRYPT_CFG_H
+
+#if defined(_WIN32) || defined(_MSC_VER)
+#define LTC_CALL __cdecl
+#else
+#ifndef LTC_CALL
+ #define LTC_CALL
+#endif
+#endif
+
+#ifndef LTC_EXPORT
+#define LTC_EXPORT
+#endif
+
+LTC_EXPORT void LTC_CALL XQSORT(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *));
+
+/* certain platforms use macros for these, making the prototypes broken */
+#ifndef LTC_NO_PROTOTYPES
+
+/* you can change how memory allocation works ... */
+LTC_EXPORT void * LTC_CALL XMALLOC(size_t n);
+LTC_EXPORT void * LTC_CALL XREALLOC(void *p, size_t n);
+LTC_EXPORT void * LTC_CALL XCALLOC(size_t n, size_t s);
+LTC_EXPORT void LTC_CALL XFREE(void *p);
+
+/* change the clock function too */
+LTC_EXPORT clock_t LTC_CALL XCLOCK(void);
+
+/* various other functions */
+LTC_EXPORT void * LTC_CALL XMEMCPY(void *dest, const void *src, size_t n);
+LTC_EXPORT int LTC_CALL XMEMCMP(const void *s1, const void *s2, size_t n);
+LTC_EXPORT void * LTC_CALL XMEMSET(void *s, int c, size_t n);
+
+LTC_EXPORT int LTC_CALL XSTRCMP(const char *s1, const char *s2);
+
+#endif
+
+/* type of argument checking, 0=default, 1=fatal and 2=error+continue, 3=nothing */
+#ifndef ARGTYPE
+ #define ARGTYPE 0
+#endif
+
+/* Controls endianess and size of registers. Leave uncommented to get platform neutral [slower] code
+ *
+ * Note: in order to use the optimized macros your platform must support unaligned 32 and 64 bit read/writes.
+ * The x86 platforms allow this but some others [ARM for instance] do not. On those platforms you **MUST**
+ * use the portable [slower] macros.
+ */
+
+/* detect x86-32 machines somewhat */
+#if !defined(__STRICT_ANSI__) && (defined(INTEL_CC) || (defined(_MSC_VER) && defined(WIN32)) || (defined(__GNUC__) && (defined(__DJGPP__) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__i386__))))
+ #define ENDIAN_LITTLE
+ #define ENDIAN_32BITWORD
+ #define LTC_FAST
+ #define LTC_FAST_TYPE unsigned long
+#endif
+
+/* detects MIPS R5900 processors (PS2) */
+#if (defined(__R5900) || defined(R5900) || defined(__R5900__)) && (defined(_mips) || defined(__mips__) || defined(mips))
+ #define ENDIAN_LITTLE
+ #define ENDIAN_64BITWORD
+#endif
+
+/* detect amd64 */
+#if !defined(__STRICT_ANSI__) && defined(__x86_64__)
+ #define ENDIAN_LITTLE
+ #define ENDIAN_64BITWORD
+ #define LTC_FAST
+ #define LTC_FAST_TYPE unsigned long
+#endif
+
+/* detect PPC32 */
+#if !defined(__STRICT_ANSI__) && defined(LTC_PPC32)
+ #define ENDIAN_BIG
+ #define ENDIAN_32BITWORD
+ #define LTC_FAST
+ #define LTC_FAST_TYPE unsigned long
+#endif
+
+/* detect sparc and sparc64 */
+#if defined(__sparc__)
+ #define ENDIAN_BIG
+ #if defined(__arch64__)
+ #define ENDIAN_64BITWORD
+ #else
+ #define ENDIAN_32BITWORD
+ #endif
+#endif
+
+
+#ifdef LTC_NO_FAST
+ #ifdef LTC_FAST
+ #undef LTC_FAST
+ #endif
+#endif
+
+/* No asm is a quick way to disable anything "not portable" */
+#ifdef LTC_NO_ASM
+ #undef ENDIAN_LITTLE
+ #undef ENDIAN_BIG
+ #undef ENDIAN_32BITWORD
+ #undef ENDIAN_64BITWORD
+ #undef LTC_FAST
+ #undef LTC_FAST_TYPE
+ #define LTC_NO_ROLC
+ #define LTC_NO_BSWAP
+#endif
+
+/* #define ENDIAN_LITTLE */
+/* #define ENDIAN_BIG */
+
+/* #define ENDIAN_32BITWORD */
+/* #define ENDIAN_64BITWORD */
+
+#if (defined(ENDIAN_BIG) || defined(ENDIAN_LITTLE)) && !(defined(ENDIAN_32BITWORD) || defined(ENDIAN_64BITWORD))
+ #error You must specify a word size as well as endianess in tomcrypt_cfg.h
+#endif
+
+#if !(defined(ENDIAN_BIG) || defined(ENDIAN_LITTLE))
+ #define ENDIAN_NEUTRAL
+#endif
+
+#endif
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_cfg.h,v $ */
+/* $Revision: 1.19 $ */
+/* $Date: 2006/12/04 02:19:48 $ */
diff --git a/crypto/userspace/libtomcrypt/headers/tomcrypt_custom.h b/crypto/userspace/libtomcrypt/headers/tomcrypt_custom.h
new file mode 100644
index 0000000..c537dc7
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/headers/tomcrypt_custom.h
@@ -0,0 +1,408 @@
+#ifndef TOMCRYPT_CUSTOM_H_
+#define TOMCRYPT_CUSTOM_H_
+
+#define LTC_NO_PROTOTYPES
+
+/* macros for various libc functions you can change for embedded targets */
+#ifndef XMALLOC
+ #ifdef malloc
+ #define LTC_NO_PROTOTYPES
+ #endif
+#define XMALLOC(x) kmalloc(x, GFP_KERNEL)
+#endif
+#ifndef XREALLOC
+ #ifdef realloc
+ #define LTC_NO_PROTOTYPES
+ #endif
+#define XREALLOC(x,y) krealloc(x,y,GFP_KERNEL)
+#endif
+#ifndef XCALLOC
+ #ifdef calloc
+ #define LTC_NO_PROTOTYPES
+ #endif
+#define XCALLOC(x,y) kcalloc(x, y, GFP_KERNEL)
+#endif
+#ifndef XFREE
+ #ifdef free
+ #define LTC_NO_PROTOTYPES
+ #endif
+#define XFREE kfree
+#endif
+
+#ifndef XMEMSET
+ #ifdef memset
+ #define LTC_NO_PROTOTYPES
+ #endif
+#define XMEMSET memset
+#endif
+#ifndef XMEMCPY
+ #ifdef memcpy
+ #define LTC_NO_PROTOTYPES
+ #endif
+#define XMEMCPY memcpy
+#endif
+#ifndef XMEMCMP
+ #ifdef memcmp
+ #define LTC_NO_PROTOTYPES
+ #endif
+#define XMEMCMP memcmp
+#endif
+#ifndef XSTRCMP
+ #ifdef strcmp
+ #define LTC_NO_PROTOTYPES
+ #endif
+#define XSTRCMP strcmp
+#endif
+
+#ifndef XCLOCK
+#define XCLOCK clock
+#endif
+#ifndef XCLOCKS_PER_SEC
+#define XCLOCKS_PER_SEC CLOCKS_PER_SEC
+#endif
+
+#ifndef XQSORT
+ #ifdef qsort
+ #define LTC_NO_PROTOTYPES
+ #endif
+#define XQSORT qsort
+#endif
+
+/* Easy button? */
+#ifdef LTC_EASY
+ #define LTC_NO_CIPHERS
+ #define LTC_RIJNDAEL
+ #define LTC_BLOWFISH
+ #define LTC_DES
+ #define LTC_CAST5
+
+ #define LTC_NO_MODES
+ #define LTC_ECB_MODE
+ #define LTC_CBC_MODE
+ #define LTC_CTR_MODE
+
+ #define LTC_NO_HASHES
+ #define LTC_SHA1
+ #define LTC_SHA512
+ #define LTC_SHA384
+ #define LTC_SHA256
+ #define LTC_SHA224
+
+ #define LTC_NO_MACS
+ #define LTC_HMAC
+ #define LTC_OMAC
+ #define LTC_CCM_MODE
+
+ #define LTC_NO_PRNGS
+ #define LTC_SPRNG
+ #define LTC_YARROW
+ #define LTC_DEVRANDOM
+ #define TRY_URANDOM_FIRST
+
+ #define LTC_NO_PK
+ #define LTC_MRSA
+ #define LTC_MECC
+#endif
+
+/* Use small code where possible */
+/* #define LTC_SMALL_CODE */
+
+/* Enable self-test test vector checking */
+#ifndef LTC_NO_TEST
+ #define LTC_TEST
+#endif
+
+/* clean the stack of functions which put private information on stack */
+/* #define LTC_CLEAN_STACK */
+
+/* disable all file related functions */
+/* #define LTC_NO_FILE */
+
+/* disable all forms of ASM */
+/* #define LTC_NO_ASM */
+
+/* disable FAST mode */
+/* #define LTC_NO_FAST */
+
+/* disable BSWAP on x86 */
+/* #define LTC_NO_BSWAP */
+
+/* ---> Symmetric Block Ciphers <--- */
+#ifndef LTC_NO_CIPHERS
+
+#define LTC_BLOWFISH
+#define LTC_RC2
+#define LTC_RC5
+#define LTC_RC6
+#define LTC_SAFERP
+#define LTC_RIJNDAEL
+#define LTC_XTEA
+/* _TABLES tells it to use tables during setup, _SMALL means to use the smaller scheduled key format
+ * (saves 4KB of ram), _ALL_TABLES enables all tables during setup */
+#define LTC_TWOFISH
+#ifndef LTC_NO_TABLES
+ #define LTC_TWOFISH_TABLES
+ /* #define LTC_TWOFISH_ALL_TABLES */
+#else
+ #define LTC_TWOFISH_SMALL
+#endif
+/* #define LTC_TWOFISH_SMALL */
+/* LTC_DES includes EDE triple-LTC_DES */
+#define LTC_DES
+#define LTC_CAST5
+#define LTC_NOEKEON
+#define LTC_SKIPJACK
+#define LTC_SAFER
+#define LTC_KHAZAD
+#define LTC_ANUBIS
+#define LTC_ANUBIS_TWEAK
+#define LTC_KSEED
+#define LTC_KASUMI
+
+#endif /* LTC_NO_CIPHERS */
+
+
+/* ---> Block Cipher Modes of Operation <--- */
+#ifndef LTC_NO_MODES
+
+#define LTC_CFB_MODE
+#define LTC_OFB_MODE
+#define LTC_ECB_MODE
+#define LTC_CBC_MODE
+#define LTC_CTR_MODE
+
+/* F8 chaining mode */
+#define LTC_F8_MODE
+
+/* LRW mode */
+#define LTC_LRW_MODE
+#ifndef LTC_NO_TABLES
+ /* like GCM mode this will enable 16 8x128 tables [64KB] that make
+ * seeking very fast.
+ */
+ #define LRW_TABLES
+#endif
+
+/* XTS mode */
+#define LTC_XTS_MODE
+
+#endif /* LTC_NO_MODES */
+
+/* ---> One-Way Hash Functions <--- */
+#ifndef LTC_NO_HASHES
+
+#define LTC_CHC_HASH
+#define LTC_WHIRLPOOL
+#define LTC_SHA512
+#define LTC_SHA384
+#define LTC_SHA256
+#define LTC_SHA224
+#define LTC_TIGER
+#define LTC_SHA1
+#define LTC_MD5
+#define LTC_MD4
+#define LTC_MD2
+#define LTC_RIPEMD128
+#define LTC_RIPEMD160
+#define LTC_RIPEMD256
+#define LTC_RIPEMD320
+
+#endif /* LTC_NO_HASHES */
+
+/* ---> MAC functions <--- */
+#ifndef LTC_NO_MACS
+
+#define LTC_HMAC
+#define LTC_OMAC
+#define LTC_PMAC
+#define LTC_XCBC
+#define LTC_F9_MODE
+#define LTC_PELICAN
+
+#if defined(LTC_PELICAN) && !defined(LTC_RIJNDAEL)
+ #error Pelican-MAC requires LTC_RIJNDAEL
+#endif
+
+/* ---> Encrypt + Authenticate Modes <--- */
+
+#define LTC_EAX_MODE
+#if defined(LTC_EAX_MODE) && !(defined(LTC_CTR_MODE) && defined(LTC_OMAC))
+ #error LTC_EAX_MODE requires CTR and LTC_OMAC mode
+#endif
+
+#define LTC_OCB_MODE
+#define LTC_CCM_MODE
+#define LTC_GCM_MODE
+
+/* Use 64KiB tables */
+#ifndef LTC_NO_TABLES
+ #define LTC_GCM_TABLES
+#endif
+
+/* USE SSE2? requires GCC works on x86_32 and x86_64*/
+#ifdef LTC_GCM_TABLES
+/* #define LTC_GCM_TABLES_SSE2 */
+#endif
+
+#endif /* LTC_NO_MACS */
+
+/* Various tidbits of modern neatoness */
+#define LTC_BASE64
+
+/* --> Pseudo Random Number Generators <--- */
+#ifndef LTC_NO_PRNGS
+
+/* Yarrow */
+#define LTC_YARROW
+/* which descriptor of AES to use? */
+/* 0 = rijndael_enc 1 = aes_enc, 2 = rijndael [full], 3 = aes [full] */
+#define LTC_YARROW_AES 0
+
+#if defined(LTC_YARROW) && !defined(LTC_CTR_MODE)
+ #error LTC_YARROW requires LTC_CTR_MODE chaining mode to be defined!
+#endif
+
+/* a PRNG that simply reads from an available system source */
+#define LTC_SPRNG
+
+/* The LTC_RC4 stream cipher */
+#define LTC_RC4
+
+/* Fortuna PRNG */
+#define LTC_FORTUNA
+/* reseed every N calls to the read function */
+#define LTC_FORTUNA_WD 10
+/* number of pools (4..32) can save a bit of ram by lowering the count */
+#define LTC_FORTUNA_POOLS 32
+
+/* Greg's LTC_SOBER128 PRNG ;-0 */
+#define LTC_SOBER128
+
+/* the *nix style /dev/random device */
+#define LTC_DEVRANDOM
+/* try /dev/urandom before trying /dev/random */
+#define TRY_URANDOM_FIRST
+
+#endif /* LTC_NO_PRNGS */
+
+/* ---> math provider? <--- */
+#ifndef LTC_NO_MATH
+
+/* LibTomMath */
+#define LTM_LTC_DESC
+
+/* TomsFastMath */
+/* #define TFM_LTC_DESC */
+
+#endif /* LTC_NO_MATH */
+
+/* ---> Public Key Crypto <--- */
+#ifndef LTC_NO_PK
+
+/* Include RSA support */
+#define LTC_MRSA
+
+/* Include Katja (a Rabin variant like RSA) */
+/* #define MKAT */
+
+/* Digital Signature Algorithm */
+#define LTC_MDSA
+
+/* ECC */
+#define LTC_MECC
+
+/* use Shamir's trick for point mul (speeds up signature verification) */
+#define LTC_ECC_SHAMIR
+
+#if defined(TFM_LTC_DESC) && defined(LTC_MECC)
+ #define LTC_MECC_ACCEL
+#endif
+
+/* do we want fixed point ECC */
+/* #define LTC_MECC_FP */
+
+/* Timing Resistant? */
+/* #define LTC_ECC_TIMING_RESISTANT */
+
+#endif /* LTC_NO_PK */
+
+/* LTC_PKCS #1 (RSA) and #5 (Password Handling) stuff */
+#ifndef LTC_NO_PKCS
+
+#define LTC_PKCS_1
+#define LTC_PKCS_5
+
+/* Include ASN.1 DER (required by DSA/RSA) */
+#define LTC_DER
+
+#endif /* LTC_NO_PKCS */
+
+/* cleanup */
+
+#ifdef LTC_MECC
+/* Supported ECC Key Sizes */
+#ifndef LTC_NO_CURVES
+ #define ECC112
+ #define ECC128
+ #define ECC160
+ #define ECC192
+ #define ECC224
+ #define ECC256
+ #define ECC384
+ #define ECC521
+#endif
+#endif
+
+#if defined(LTC_MECC) || defined(LTC_MRSA) || defined(LTC_MDSA) || defined(MKATJA)
+ /* Include the MPI functionality? (required by the PK algorithms) */
+ #define MPI
+#endif
+
+#ifdef LTC_MRSA
+ #define LTC_PKCS_1
+#endif
+
+#if defined(LTC_DER) && !defined(MPI)
+ #error ASN.1 DER requires MPI functionality
+#endif
+
+#if (defined(LTC_MDSA) || defined(LTC_MRSA) || defined(LTC_MECC) || defined(MKATJA)) && !defined(LTC_DER)
+ #error PK requires ASN.1 DER functionality, make sure LTC_DER is enabled
+#endif
+
+/* THREAD management */
+#ifdef LTC_PTHREAD
+
+#include <pthread.h>
+
+#define LTC_MUTEX_GLOBAL(x) pthread_mutex_t x = PTHREAD_MUTEX_INITIALIZER;
+#define LTC_MUTEX_PROTO(x) extern pthread_mutex_t x;
+#define LTC_MUTEX_TYPE(x) pthread_mutex_t x;
+#define LTC_MUTEX_INIT(x) pthread_mutex_init(x, NULL);
+#define LTC_MUTEX_LOCK(x) pthread_mutex_lock(x);
+#define LTC_MUTEX_UNLOCK(x) pthread_mutex_unlock(x);
+
+#else
+
+/* default no functions */
+#define LTC_MUTEX_GLOBAL(x)
+#define LTC_MUTEX_PROTO(x)
+#define LTC_MUTEX_TYPE(x)
+#define LTC_MUTEX_INIT(x)
+#define LTC_MUTEX_LOCK(x)
+#define LTC_MUTEX_UNLOCK(x)
+
+#endif
+
+/* Debuggers */
+
+/* define this if you use Valgrind, note: it CHANGES the way SOBER-128 and LTC_RC4 work (see the code) */
+/* #define LTC_VALGRIND */
+
+#endif
+
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_custom.h,v $ */
+/* $Revision: 1.73 $ */
+/* $Date: 2007/05/12 14:37:41 $ */
diff --git a/crypto/userspace/libtomcrypt/headers/tomcrypt_hash.h b/crypto/userspace/libtomcrypt/headers/tomcrypt_hash.h
new file mode 100644
index 0000000..e4e84e4
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/headers/tomcrypt_hash.h
@@ -0,0 +1,14 @@
+/* ---- HASH FUNCTIONS ---- */
+
+struct algo_properties_st;
+
+int hash_is_valid(const struct algo_properties_st *hash);
+
+int hash_memory(const struct algo_properties_st *hash,
+ const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+int hash_memory_multi(const struct algo_properties_st *hash, unsigned char *out, unsigned long *outlen,
+ const unsigned char *in, unsigned long inlen, ...);
+
+int hash_get_oid(const struct algo_properties_st *hash, oid_st* st);
+
diff --git a/crypto/userspace/libtomcrypt/headers/tomcrypt_macros.h b/crypto/userspace/libtomcrypt/headers/tomcrypt_macros.h
new file mode 100644
index 0000000..53bda9b
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/headers/tomcrypt_macros.h
@@ -0,0 +1,424 @@
+/* fix for MSVC ...evil! */
+#ifdef _MSC_VER
+ #define CONST64(n) n ## ui64
+ typedef unsigned __int64 ulong64;
+#else
+ #define CONST64(n) n ## ULL
+ typedef unsigned long long ulong64;
+#endif
+
+/* this is the "32-bit at least" data type
+ * Re-define it to suit your platform but it must be at least 32-bits
+ */
+#if defined(__x86_64__) || (defined(__sparc__) && defined(__arch64__))
+ typedef unsigned ulong32;
+#else
+ typedef unsigned long ulong32;
+#endif
+
+/* ---- HELPER MACROS ---- */
+#ifdef ENDIAN_NEUTRAL
+
+#define STORE32L(x, y) \
+ { (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
+ (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
+
+#define LOAD32L(x, y) \
+ { x = ((unsigned long)((y)[3] & 255)<<24) | \
+ ((unsigned long)((y)[2] & 255)<<16) | \
+ ((unsigned long)((y)[1] & 255)<<8) | \
+ ((unsigned long)((y)[0] & 255)); }
+
+#define STORE64L(x, y) \
+ { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \
+ (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \
+ (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
+ (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
+
+#define LOAD64L(x, y) \
+ { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48)| \
+ (((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32)| \
+ (((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16)| \
+ (((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); }
+
+#define STORE32H(x, y) \
+ { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \
+ (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); }
+
+#define LOAD32H(x, y) \
+ { x = ((unsigned long)((y)[0] & 255)<<24) | \
+ ((unsigned long)((y)[1] & 255)<<16) | \
+ ((unsigned long)((y)[2] & 255)<<8) | \
+ ((unsigned long)((y)[3] & 255)); }
+
+#define STORE64H(x, y) \
+ { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \
+ (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \
+ (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \
+ (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); }
+
+#define LOAD64H(x, y) \
+ { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48) | \
+ (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32) | \
+ (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16) | \
+ (((ulong64)((y)[6] & 255))<<8)|(((ulong64)((y)[7] & 255))); }
+
+#endif /* ENDIAN_NEUTRAL */
+
+#ifdef ENDIAN_LITTLE
+
+#if !defined(LTC_NO_BSWAP) && (defined(INTEL_CC) || (defined(__GNUC__) && (defined(__DJGPP__) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__i386__) || defined(__x86_64__))))
+
+#define STORE32H(x, y) \
+asm __volatile__ ( \
+ "bswapl %0 \n\t" \
+ "movl %0,(%1)\n\t" \
+ "bswapl %0 \n\t" \
+ ::"r"(x), "r"(y));
+
+#define LOAD32H(x, y) \
+asm __volatile__ ( \
+ "movl (%1),%0\n\t" \
+ "bswapl %0\n\t" \
+ :"=r"(x): "r"(y));
+
+#else
+
+#define STORE32H(x, y) \
+ { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \
+ (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); }
+
+#define LOAD32H(x, y) \
+ { x = ((unsigned long)((y)[0] & 255)<<24) | \
+ ((unsigned long)((y)[1] & 255)<<16) | \
+ ((unsigned long)((y)[2] & 255)<<8) | \
+ ((unsigned long)((y)[3] & 255)); }
+
+#endif
+
+
+/* x86_64 processor */
+#if !defined(LTC_NO_BSWAP) && (defined(__GNUC__) && defined(__x86_64__))
+
+#define STORE64H(x, y) \
+asm __volatile__ ( \
+ "bswapq %0 \n\t" \
+ "movq %0,(%1)\n\t" \
+ "bswapq %0 \n\t" \
+ ::"r"(x), "r"(y));
+
+#define LOAD64H(x, y) \
+asm __volatile__ ( \
+ "movq (%1),%0\n\t" \
+ "bswapq %0\n\t" \
+ :"=r"(x): "r"(y));
+
+#else
+
+#define STORE64H(x, y) \
+ { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \
+ (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \
+ (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \
+ (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); }
+
+#define LOAD64H(x, y) \
+ { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48) | \
+ (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32) | \
+ (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16) | \
+ (((ulong64)((y)[6] & 255))<<8)|(((ulong64)((y)[7] & 255))); }
+
+#endif
+
+#ifdef ENDIAN_32BITWORD
+
+#define STORE32L(x, y) \
+ { ulong32 __t = (x); XMEMCPY(y, &__t, 4); }
+
+#define LOAD32L(x, y) \
+ XMEMCPY(&(x), y, 4);
+
+#define STORE64L(x, y) \
+ { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \
+ (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \
+ (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
+ (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
+
+#define LOAD64L(x, y) \
+ { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48)| \
+ (((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32)| \
+ (((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16)| \
+ (((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); }
+
+#else /* 64-bit words then */
+
+#define STORE32L(x, y) \
+ { ulong32 __t = (x); XMEMCPY(y, &__t, 4); }
+
+#define LOAD32L(x, y) \
+ { XMEMCPY(&(x), y, 4); x &= 0xFFFFFFFF; }
+
+#define STORE64L(x, y) \
+ { ulong64 __t = (x); XMEMCPY(y, &__t, 8); }
+
+#define LOAD64L(x, y) \
+ { XMEMCPY(&(x), y, 8); }
+
+#endif /* ENDIAN_64BITWORD */
+
+#endif /* ENDIAN_LITTLE */
+
+#ifdef ENDIAN_BIG
+#define STORE32L(x, y) \
+ { (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
+ (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
+
+#define LOAD32L(x, y) \
+ { x = ((unsigned long)((y)[3] & 255)<<24) | \
+ ((unsigned long)((y)[2] & 255)<<16) | \
+ ((unsigned long)((y)[1] & 255)<<8) | \
+ ((unsigned long)((y)[0] & 255)); }
+
+#define STORE64L(x, y) \
+ { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \
+ (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \
+ (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
+ (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
+
+#define LOAD64L(x, y) \
+ { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48) | \
+ (((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32) | \
+ (((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16) | \
+ (((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); }
+
+#ifdef ENDIAN_32BITWORD
+
+#define STORE32H(x, y) \
+ { ulong32 __t = (x); XMEMCPY(y, &__t, 4); }
+
+#define LOAD32H(x, y) \
+ XMEMCPY(&(x), y, 4);
+
+#define STORE64H(x, y) \
+ { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \
+ (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \
+ (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \
+ (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); }
+
+#define LOAD64H(x, y) \
+ { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48)| \
+ (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32)| \
+ (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16)| \
+ (((ulong64)((y)[6] & 255))<<8)| (((ulong64)((y)[7] & 255))); }
+
+#else /* 64-bit words then */
+
+#define STORE32H(x, y) \
+ { ulong32 __t = (x); XMEMCPY(y, &__t, 4); }
+
+#define LOAD32H(x, y) \
+ { XMEMCPY(&(x), y, 4); x &= 0xFFFFFFFF; }
+
+#define STORE64H(x, y) \
+ { ulong64 __t = (x); XMEMCPY(y, &__t, 8); }
+
+#define LOAD64H(x, y) \
+ { XMEMCPY(&(x), y, 8); }
+
+#endif /* ENDIAN_64BITWORD */
+#endif /* ENDIAN_BIG */
+
+#define BSWAP(x) ( ((x>>24)&0x000000FFUL) | ((x<<24)&0xFF000000UL) | \
+ ((x>>8)&0x0000FF00UL) | ((x<<8)&0x00FF0000UL) )
+
+
+/* 32-bit Rotates */
+#if defined(_MSC_VER)
+
+/* instrinsic rotate */
+#include <stdlib.h>
+#pragma intrinsic(_lrotr,_lrotl)
+#define ROR(x,n) _lrotr(x,n)
+#define ROL(x,n) _lrotl(x,n)
+#define RORc(x,n) _lrotr(x,n)
+#define ROLc(x,n) _lrotl(x,n)
+
+#elif !defined(__STRICT_ANSI__) && defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && !defined(INTEL_CC) && !defined(LTC_NO_ASM)
+
+static inline unsigned ROL(unsigned word, int i)
+{
+ asm ("roll %%cl,%0"
+ :"=r" (word)
+ :"0" (word),"c" (i));
+ return word;
+}
+
+static inline unsigned ROR(unsigned word, int i)
+{
+ asm ("rorl %%cl,%0"
+ :"=r" (word)
+ :"0" (word),"c" (i));
+ return word;
+}
+
+#ifndef LTC_NO_ROLC
+
+static inline unsigned ROLc(unsigned word, const int i)
+{
+ asm ("roll %2,%0"
+ :"=r" (word)
+ :"0" (word),"I" (i));
+ return word;
+}
+
+static inline unsigned RORc(unsigned word, const int i)
+{
+ asm ("rorl %2,%0"
+ :"=r" (word)
+ :"0" (word),"I" (i));
+ return word;
+}
+
+#else
+
+#define ROLc ROL
+#define RORc ROR
+
+#endif
+
+#elif !defined(__STRICT_ANSI__) && defined(LTC_PPC32)
+
+static inline unsigned ROL(unsigned word, int i)
+{
+ asm ("rotlw %0,%0,%2"
+ :"=r" (word)
+ :"0" (word),"r" (i));
+ return word;
+}
+
+static inline unsigned ROR(unsigned word, int i)
+{
+ asm ("rotlw %0,%0,%2"
+ :"=r" (word)
+ :"0" (word),"r" (32-i));
+ return word;
+}
+
+#ifndef LTC_NO_ROLC
+
+static inline unsigned ROLc(unsigned word, const int i)
+{
+ asm ("rotlwi %0,%0,%2"
+ :"=r" (word)
+ :"0" (word),"I" (i));
+ return word;
+}
+
+static inline unsigned RORc(unsigned word, const int i)
+{
+ asm ("rotrwi %0,%0,%2"
+ :"=r" (word)
+ :"0" (word),"I" (i));
+ return word;
+}
+
+#else
+
+#define ROLc ROL
+#define RORc ROR
+
+#endif
+
+
+#else
+
+/* rotates the hard way */
+#define ROL(x, y) ( (((unsigned long)(x)<<(unsigned long)((y)&31)) | (((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
+#define ROR(x, y) ( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | ((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
+#define ROLc(x, y) ( (((unsigned long)(x)<<(unsigned long)((y)&31)) | (((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
+#define RORc(x, y) ( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | ((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
+
+#endif
+
+
+/* 64-bit Rotates */
+#if !defined(__STRICT_ANSI__) && defined(__GNUC__) && defined(__x86_64__) && !defined(LTC_NO_ASM)
+
+static inline unsigned long ROL64(unsigned long word, int i)
+{
+ asm("rolq %%cl,%0"
+ :"=r" (word)
+ :"0" (word),"c" (i));
+ return word;
+}
+
+static inline unsigned long ROR64(unsigned long word, int i)
+{
+ asm("rorq %%cl,%0"
+ :"=r" (word)
+ :"0" (word),"c" (i));
+ return word;
+}
+
+#ifndef LTC_NO_ROLC
+
+static inline unsigned long ROL64c(unsigned long word, const int i)
+{
+ asm("rolq %2,%0"
+ :"=r" (word)
+ :"0" (word),"J" (i));
+ return word;
+}
+
+static inline unsigned long ROR64c(unsigned long word, const int i)
+{
+ asm("rorq %2,%0"
+ :"=r" (word)
+ :"0" (word),"J" (i));
+ return word;
+}
+
+#else /* LTC_NO_ROLC */
+
+#define ROL64c ROL64
+#define ROR64c ROR64
+
+#endif
+
+#else /* Not x86_64 */
+
+#define ROL64(x, y) \
+ ( (((x)<<((ulong64)(y)&63)) | \
+ (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)64-((y)&63)))) & CONST64(0xFFFFFFFFFFFFFFFF))
+
+#define ROR64(x, y) \
+ ( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)(y)&CONST64(63))) | \
+ ((x)<<((ulong64)(64-((y)&CONST64(63)))))) & CONST64(0xFFFFFFFFFFFFFFFF))
+
+#define ROL64c(x, y) \
+ ( (((x)<<((ulong64)(y)&63)) | \
+ (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)64-((y)&63)))) & CONST64(0xFFFFFFFFFFFFFFFF))
+
+#define ROR64c(x, y) \
+ ( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)(y)&CONST64(63))) | \
+ ((x)<<((ulong64)(64-((y)&CONST64(63)))))) & CONST64(0xFFFFFFFFFFFFFFFF))
+
+#endif
+
+#ifndef MAX
+ #define MAX(x, y) ( ((x)>(y))?(x):(y) )
+#endif
+
+#ifndef MIN
+ #define MIN(x, y) ( ((x)<(y))?(x):(y) )
+#endif
+
+/* extract a byte portably */
+#ifdef _MSC_VER
+ #define byte(x, n) ((unsigned char)((x) >> (8 * (n))))
+#else
+ #define byte(x, n) (((x) >> (8 * (n))) & 255)
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_macros.h,v $ */
+/* $Revision: 1.15 $ */
+/* $Date: 2006/11/29 23:43:57 $ */
diff --git a/crypto/userspace/libtomcrypt/headers/tomcrypt_math.h b/crypto/userspace/libtomcrypt/headers/tomcrypt_math.h
new file mode 100644
index 0000000..6c0e6c5
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/headers/tomcrypt_math.h
@@ -0,0 +1,13 @@
+/** math functions **/
+
+#define LTC_MP_LT -1
+#define LTC_MP_EQ 0
+#define LTC_MP_GT 1
+
+#define LTC_MP_NO 0
+#define LTC_MP_YES 1
+
+#include <tommath.h>
+
+typedef mp_int* mp_int_t;
+
diff --git a/crypto/userspace/libtomcrypt/headers/tomcrypt_misc.h b/crypto/userspace/libtomcrypt/headers/tomcrypt_misc.h
new file mode 100644
index 0000000..f5384ca
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/headers/tomcrypt_misc.h
@@ -0,0 +1,23 @@
+/* ---- LTC_BASE64 Routines ---- */
+#ifdef LTC_BASE64
+int base64_encode(const unsigned char *in, unsigned long len,
+ unsigned char *out, unsigned long *outlen);
+
+int base64_decode(const unsigned char *in, unsigned long len,
+ unsigned char *out, unsigned long *outlen);
+#endif
+
+/* ---- MEM routines ---- */
+void zeromem(void *dst, size_t len);
+void burn_stack(unsigned long len);
+
+const char *error_to_string(int err);
+
+extern const char *crypt_build_settings;
+
+/* ---- HMM ---- */
+int crypt_fsa(void *mp, ...);
+
+/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_misc.h,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/headers/tomcrypt_pk.h b/crypto/userspace/libtomcrypt/headers/tomcrypt_pk.h
new file mode 100644
index 0000000..145165e
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/headers/tomcrypt_pk.h
@@ -0,0 +1,359 @@
+/* ---- NUMBER THEORY ---- */
+
+struct algo_properties_st;
+
+enum {
+ PK_PUBLIC=0,
+ PK_PRIVATE=1
+};
+
+enum {
+ PKA_RSA,
+ PKA_DSA
+};
+
+typedef struct Oid {
+ unsigned long OID[16];
+ /** Length of DER encoding */
+ unsigned long OIDlen;
+} oid_st;
+
+int pk_get_oid(int pk, oid_st *st);
+int rand_prime(mp_int *N, long len);
+
+/* ---- RSA ---- */
+#ifdef LTC_MRSA
+
+/* Min and Max RSA key sizes (in bits) */
+#define MIN_RSA_SIZE 1024
+#define MAX_RSA_SIZE 4096
+
+/** RSA LTC_PKCS style key */
+typedef struct Rsa_key {
+ /** Type of key, PK_PRIVATE or PK_PUBLIC */
+ int type;
+ /** The public exponent */
+ mp_int e;
+ /** The private exponent */
+ mp_int d;
+ /** The modulus */
+ mp_int N;
+ /** The p factor of N */
+ mp_int p;
+ /** The q factor of N */
+ mp_int q;
+ /** The 1/q mod p CRT param */
+ mp_int qP;
+ /** The d mod (p - 1) CRT param */
+ mp_int dP;
+ /** The d mod (q - 1) CRT param */
+ mp_int dQ;
+} rsa_key;
+
+int rsa_make_key(int size, long e, rsa_key *key);
+
+int rsa_exptmod(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen, int which,
+ rsa_key *key);
+
+void rsa_free(rsa_key *key);
+
+/* These use LTC_PKCS #1 v2.0 padding */
+#define rsa_encrypt_key(_in, _inlen, _out, _outlen, _lparam, _lparamlen, _hash, _key) \
+ rsa_encrypt_key_ex(_in, _inlen, _out, _outlen, _lparam, _lparamlen, _hash, LTC_LTC_PKCS_1_OAEP, _key)
+
+#define rsa_decrypt_key(_in, _inlen, _out, _outlen, _lparam, _lparamlen, _hash, _stat, _key) \
+ rsa_decrypt_key_ex(_in, _inlen, _out, _outlen, _lparam, _lparamlen, _hash, LTC_LTC_PKCS_1_OAEP, _stat, _key)
+
+#define rsa_sign_hash(_in, _inlen, _out, _outlen, _hash, _saltlen, _key) \
+ rsa_sign_hash_ex(_in, _inlen, _out, _outlen, LTC_LTC_PKCS_1_PSS, _hash, _saltlen, _key)
+
+#define rsa_verify_hash(_sig, _siglen, _hash, _hashlen, _hash_algo, _saltlen, _stat, _key) \
+ rsa_verify_hash_ex(_sig, _siglen, _hash, _hashlen, LTC_LTC_PKCS_1_PSS, _hash_algo, _saltlen, _stat, _key)
+
+/* These can be switched between LTC_PKCS #1 v2.x and LTC_PKCS #1 v1.5 paddings */
+int rsa_encrypt_key_ex(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ const unsigned char *lparam, unsigned long lparamlen,
+ const struct algo_properties_st *hash, int padding, rsa_key *key);
+
+int rsa_decrypt_key_ex(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ const unsigned char *lparam, unsigned long lparamlen,
+ const struct algo_properties_st *hash, int padding,
+ int *stat, rsa_key *key);
+
+int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ int padding,
+ const struct algo_properties_st *hash, unsigned long saltlen,
+ rsa_key *key);
+
+int rsa_verify_hash_ex(const unsigned char *sig, unsigned long siglen,
+ const unsigned char *hash, unsigned long hashlen,
+ int padding,
+ const struct algo_properties_st *hash_algo, unsigned long saltlen,
+ int *stat, rsa_key *key);
+
+/* LTC_PKCS #1 import/export */
+int rsa_export(unsigned char *out, unsigned long *outlen, int type, rsa_key *key);
+int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key);
+
+#endif
+
+
+#ifdef LTC_MDSA
+
+/* Max diff between group and modulus size in bytes */
+#define LTC_MDSA_DELTA 512
+
+/* Max DSA group size in bytes (default allows 4k-bit groups) */
+#define LTC_MDSA_MAX_GROUP 512
+
+/** DSA key structure */
+typedef struct {
+ /** The key type, PK_PRIVATE or PK_PUBLIC */
+ int type;
+
+ /** The order of the sub-group used in octets */
+ int qord;
+
+ /** The generator */
+ mp_int g;
+
+ /** The prime used to generate the sub-group */
+ mp_int q;
+
+ /** The large prime that generats the field the contains the sub-group */
+ mp_int p;
+
+ /** The private key */
+ mp_int x;
+
+ /** The public key */
+ mp_int y;
+} dsa_key;
+
+int dsa_make_key(int group_size, int modulus_size, dsa_key *key);
+void dsa_free(dsa_key *key);
+
+int dsa_sign_hash_raw(const unsigned char *in, unsigned long inlen,
+ mp_int_t r, mp_int_t s,
+ dsa_key *key);
+
+int dsa_sign_hash(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ dsa_key *key);
+
+int dsa_verify_hash_raw( mp_int_t r, mp_int_t s,
+ const unsigned char *hash, unsigned long hashlen,
+ int *stat, dsa_key *key);
+
+int dsa_verify_hash(const unsigned char *sig, unsigned long siglen,
+ const unsigned char *hash, unsigned long hashlen,
+ int *stat, dsa_key *key);
+
+int dsa_encrypt_key(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ int hash, dsa_key *key);
+
+int dsa_decrypt_key(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ dsa_key *key);
+
+int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key);
+int dsa_export(unsigned char *out, unsigned long *outlen, int type, dsa_key *key);
+int dsa_verify_key(dsa_key *key, int *stat);
+
+int dsa_shared_secret(void *private_key, mp_int_t base,
+ dsa_key *public_key,
+ unsigned char *out, unsigned long *outlen);
+#endif
+
+#ifdef LTC_DER
+/* DER handling */
+
+enum {
+ LTC_ASN1_EOL,
+ LTC_ASN1_BOOLEAN,
+ LTC_ASN1_INTEGER,
+ LTC_ASN1_SHORT_INTEGER,
+ LTC_ASN1_BIT_STRING,
+ LTC_ASN1_OCTET_STRING,
+ LTC_ASN1_NULL,
+ LTC_ASN1_OBJECT_IDENTIFIER,
+ LTC_ASN1_IA5_STRING,
+ LTC_ASN1_PRINTABLE_STRING,
+ LTC_ASN1_UTF8_STRING,
+ LTC_ASN1_UTCTIME,
+ LTC_ASN1_CHOICE,
+ LTC_ASN1_SEQUENCE,
+ LTC_ASN1_SET,
+ LTC_ASN1_SETOF
+};
+
+/** A LTC ASN.1 list type */
+typedef struct ltc_asn1_list_ {
+ /** The LTC ASN.1 enumerated type identifier */
+ int type;
+ /** The data to encode or place for decoding */
+ void *data;
+ /** The size of the input or resulting output */
+ unsigned long size;
+ /** The used flag, this is used by the CHOICE ASN.1 type to indicate which choice was made */
+ int used;
+ /** prev/next entry in the list */
+ struct ltc_asn1_list_ *prev, *next, *child, *parent;
+} ltc_asn1_list;
+
+#define LTC_SET_ASN1(list, index, Type, Data, Size) \
+ do { \
+ int LTC_MACRO_temp = (index); \
+ ltc_asn1_list *LTC_MACRO_list = (list); \
+ LTC_MACRO_list[LTC_MACRO_temp].type = (Type); \
+ LTC_MACRO_list[LTC_MACRO_temp].data = (void*)(Data); \
+ LTC_MACRO_list[LTC_MACRO_temp].size = (Size); \
+ LTC_MACRO_list[LTC_MACRO_temp].used = 0; \
+ } while (0);
+
+/* SEQUENCE */
+int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen, int type_of);
+
+#define der_encode_sequence(list, inlen, out, outlen) der_encode_sequence_ex(list, inlen, out, outlen, LTC_ASN1_SEQUENCE)
+
+int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen,
+ ltc_asn1_list *list, unsigned long outlen, int ordered);
+
+#define der_decode_sequence(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, 1)
+
+int der_length_sequence(ltc_asn1_list *list, unsigned long inlen,
+ unsigned long *outlen);
+
+/* SUBJECT PUBLIC KEY INFO */
+int der_encode_subject_public_key_info(unsigned char *out, unsigned long *outlen,
+ unsigned int algorithm, void* public_key, unsigned long public_key_len,
+ unsigned long parameters_type, void* parameters, unsigned long parameters_len);
+
+int der_decode_subject_public_key_info(const unsigned char *in, unsigned long inlen,
+ unsigned int algorithm, void* public_key, unsigned long* public_key_len,
+ unsigned long parameters_type, ltc_asn1_list* parameters, unsigned long parameters_len);
+
+/* SET */
+#define der_decode_set(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, 0)
+#define der_length_set der_length_sequence
+int der_encode_set(ltc_asn1_list *list, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+
+int der_encode_setof(ltc_asn1_list *list, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+
+/* VA list handy helpers with triplets of <type, size, data> */
+int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...);
+int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...);
+
+/* FLEXI DECODER handle unknown list decoder */
+int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out);
+void der_free_sequence_flexi(ltc_asn1_list *list);
+void der_sequence_free(ltc_asn1_list *in);
+
+/* BOOLEAN */
+int der_length_boolean(unsigned long *outlen);
+int der_encode_boolean(int in,
+ unsigned char *out, unsigned long *outlen);
+int der_decode_boolean(const unsigned char *in, unsigned long inlen,
+ int *out);
+/* INTEGER */
+int der_encode_integer(mp_int_t num, unsigned char *out, unsigned long *outlen);
+int der_decode_integer(const unsigned char *in, unsigned long inlen, mp_int_t num);
+int der_length_integer(mp_int_t num, unsigned long *len);
+
+/* INTEGER -- handy for 0..2^32-1 values */
+int der_decode_short_integer(const unsigned char *in, unsigned long inlen, unsigned long *num);
+int der_encode_short_integer(unsigned long num, unsigned char *out, unsigned long *outlen);
+int der_length_short_integer(unsigned long num, unsigned long *outlen);
+
+/* BIT STRING */
+int der_encode_bit_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+int der_decode_bit_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+int der_length_bit_string(unsigned long nbits, unsigned long *outlen);
+
+/* OCTET STRING */
+int der_encode_octet_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+int der_decode_octet_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+int der_length_octet_string(unsigned long noctets, unsigned long *outlen);
+
+/* OBJECT IDENTIFIER */
+int der_encode_object_identifier(unsigned long *words, unsigned long nwords,
+ unsigned char *out, unsigned long *outlen);
+int der_decode_object_identifier(const unsigned char *in, unsigned long inlen,
+ unsigned long *words, unsigned long *outlen);
+int der_length_object_identifier(unsigned long *words, unsigned long nwords, unsigned long *outlen);
+unsigned long der_object_identifier_bits(unsigned long x);
+
+/* IA5 STRING */
+int der_encode_ia5_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+int der_decode_ia5_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+int der_length_ia5_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen);
+
+int der_ia5_char_encode(int c);
+int der_ia5_value_decode(int v);
+
+/* Printable STRING */
+int der_encode_printable_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+int der_decode_printable_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+int der_length_printable_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen);
+
+int der_printable_char_encode(int c);
+int der_printable_value_decode(int v);
+
+/* UTF-8 */
+
+int der_encode_utf8_string(const wchar_t *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen);
+
+int der_decode_utf8_string(const unsigned char *in, unsigned long inlen,
+ wchar_t *out, unsigned long *outlen);
+unsigned long der_utf8_charsize(const wchar_t c);
+int der_length_utf8_string(const wchar_t *in, unsigned long noctets, unsigned long *outlen);
+
+
+/* CHOICE */
+int der_decode_choice(const unsigned char *in, unsigned long *inlen,
+ ltc_asn1_list *list, unsigned long outlen);
+
+/* UTCTime */
+typedef struct {
+ unsigned YY, /* year */
+ MM, /* month */
+ DD, /* day */
+ hh, /* hour */
+ mm, /* minute */
+ ss, /* second */
+ off_dir, /* timezone offset direction 0 == +, 1 == - */
+ off_hh, /* timezone offset hours */
+ off_mm; /* timezone offset minutes */
+} ltc_utctime;
+
+int der_encode_utctime(ltc_utctime *utctime,
+ unsigned char *out, unsigned long *outlen);
+
+int der_decode_utctime(const unsigned char *in, unsigned long *inlen,
+ ltc_utctime *out);
+
+int der_length_utctime(ltc_utctime *utctime, unsigned long *outlen);
+
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_pk.h,v $ */
+/* $Revision: 1.81 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/headers/tomcrypt_pkcs.h b/crypto/userspace/libtomcrypt/headers/tomcrypt_pkcs.h
new file mode 100644
index 0000000..be0d7f6
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/headers/tomcrypt_pkcs.h
@@ -0,0 +1,67 @@
+/* LTC_PKCS Header Info */
+
+/* ===> LTC_PKCS #1 -- RSA Cryptography <=== */
+#ifdef LTC_PKCS_1
+
+struct algo_properties_st;
+
+enum ltc_pkcs_1_v1_5_blocks
+{
+ LTC_LTC_PKCS_1_EMSA = 1, /* Block type 1 (LTC_PKCS #1 v1.5 signature padding) */
+ LTC_LTC_PKCS_1_EME = 2 /* Block type 2 (LTC_PKCS #1 v1.5 encryption padding) */
+};
+
+enum ltc_pkcs_1_paddings
+{
+ LTC_LTC_PKCS_1_V1_5 = 1, /* LTC_PKCS #1 v1.5 padding (\sa ltc_pkcs_1_v1_5_blocks) */
+ LTC_LTC_PKCS_1_OAEP = 2, /* LTC_PKCS #1 v2.0 encryption padding */
+ LTC_LTC_PKCS_1_PSS = 3 /* LTC_PKCS #1 v2.1 signature padding */
+};
+
+int pkcs_1_mgf1(const struct algo_properties_st *hash,
+ const unsigned char *seed, unsigned long seedlen,
+ unsigned char *mask, unsigned long masklen);
+
+int pkcs_1_i2osp(void *n, unsigned long modulus_len, unsigned char *out);
+int pkcs_1_os2ip(void *n, unsigned char *in, unsigned long inlen);
+
+/* *** v1.5 padding */
+int pkcs_1_v1_5_encode(const unsigned char *msg,
+ unsigned long msglen,
+ int block_type,
+ unsigned long modulus_bitlen,
+ unsigned char *out,
+ unsigned long *outlen);
+
+int pkcs_1_v1_5_decode(const unsigned char *msg,
+ unsigned long msglen,
+ int block_type,
+ unsigned long modulus_bitlen,
+ unsigned char *out,
+ unsigned long *outlen,
+ int *is_valid);
+
+/* *** v2.1 padding */
+int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen,
+ const unsigned char *lparam, unsigned long lparamlen,
+ unsigned long modulus_bitlen, const struct algo_properties_st *hash,
+ unsigned char *out, unsigned long *outlen);
+
+int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen,
+ const unsigned char *lparam, unsigned long lparamlen,
+ unsigned long modulus_bitlen, const struct algo_properties_st *hash,
+ unsigned char *out, unsigned long *outlen,
+ int *res);
+
+int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen,
+ unsigned long saltlen, const struct algo_properties_st *hash,
+ unsigned long modulus_bitlen,
+ unsigned char *out, unsigned long *outlen);
+
+int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen,
+ const unsigned char *sig, unsigned long siglen,
+ unsigned long saltlen, const struct algo_properties_st *hash,
+ unsigned long modulus_bitlen, int *res);
+
+#endif /* LTC_PKCS_1 */
+
--
1.7.2.1

2010-08-20 08:45:50

by Miloslav Trmac

[permalink] [raw]
Subject: [PATCH 07/19] Add crypto API utilities.

This encapsulates allocation/deallocation of all necessary objects,
dealing with the asynchronous nature of ablkcipher/ahash.

Long term, I'm not quite sure this layer makes sense; For now, it
provides a truly simple API for internal callers in libtomcrypt, at
least.
---
crypto/userspace/Makefile | 2 +-
crypto/userspace/cryptodev_cipher.c | 339 +++++++++++++++++++++++++++++++++++
crypto/userspace/cryptodev_main.c | 13 ++
3 files changed, 353 insertions(+), 1 deletions(-)
create mode 100644 crypto/userspace/cryptodev_cipher.c
create mode 100644 crypto/userspace/cryptodev_main.c

diff --git a/crypto/userspace/Makefile b/crypto/userspace/Makefile
index f7f3ea2..a37969b 100644
--- a/crypto/userspace/Makefile
+++ b/crypto/userspace/Makefile
@@ -1,6 +1,6 @@
ccflags-y += -I$(src)/libtommath -I$(src)/libtomcrypt/headers -I$(src) -DLTC_SOURCE

-cryptodev-objs := utils.o
+cryptodev-objs := cryptodev_main.o cryptodev_cipher.o utils.o


obj-$(CONFIG_CRYPTO_USERSPACE) += cryptodev.o
diff --git a/crypto/userspace/cryptodev_cipher.c b/crypto/userspace/cryptodev_cipher.c
new file mode 100644
index 0000000..4e74fcc
--- /dev/null
+++ b/crypto/userspace/cryptodev_cipher.c
@@ -0,0 +1,339 @@
+/*
+ * Driver for /dev/crypto device (aka CryptoDev)
+ *
+ * Copyright (c) 2010 Nikos Mavrogiannopoulos <[email protected]>
+ * Portions Copyright (c) 2010 Michael Weiser
+ * Portions Copyright (c) 2010 Phil Sutter
+ *
+ * This file is part of linux cryptodev.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <linux/crypto.h>
+#include <linux/mm.h>
+#include <linux/highmem.h>
+#include <linux/ioctl.h>
+#include <linux/random.h>
+#include <linux/scatterlist.h>
+#include <linux/uaccess.h>
+#include <crypto/algapi.h>
+#include <crypto/hash.h>
+#include "cryptodev_int.h"
+
+
+struct cryptodev_result {
+ struct completion completion;
+ int err;
+};
+
+static void cryptodev_complete(struct crypto_async_request *req, int err)
+{
+ struct cryptodev_result *res = req->data;
+
+ if (err == -EINPROGRESS)
+ return;
+
+ res->err = err;
+ complete(&res->completion);
+}
+
+int cryptodev_cipher_init(struct cipher_data* out, const char* alg_name, uint8_t * keyp, size_t keylen)
+{
+
+ struct ablkcipher_alg* alg;
+ int ret;
+
+ memset(out, 0, sizeof(*out));
+
+ out->async.s = crypto_alloc_ablkcipher(alg_name, 0, 0);
+ if (unlikely(IS_ERR(out->async.s))) {
+ dprintk(1,KERN_DEBUG,"%s: Failed to load cipher %s\n", __func__,
+ alg_name);
+ return -EINVAL;
+ }
+
+ alg = crypto_ablkcipher_alg(out->async.s);
+
+ if (alg != NULL) {
+ /* Was correct key length supplied? */
+ if (alg->max_keysize > 0 && unlikely((keylen < alg->min_keysize) ||
+ (keylen > alg->max_keysize))) {
+ dprintk(1,KERN_DEBUG,"Wrong keylen '%zu' for algorithm '%s'. Use %u to %u.\n",
+ keylen, alg_name, alg->min_keysize,
+ alg->max_keysize);
+ ret = -EINVAL;
+ goto error;
+ }
+ }
+
+ ret = crypto_ablkcipher_setkey(out->async.s, keyp, keylen);
+ if (unlikely(ret)) {
+ dprintk(1,KERN_DEBUG,"Setting key failed for %s-%zu.\n",
+ alg_name, keylen*8);
+ ret = -EINVAL;
+ goto error;
+ }
+
+ out->blocksize = crypto_ablkcipher_blocksize(out->async.s);
+ out->ivsize = crypto_ablkcipher_ivsize(out->async.s);
+
+ out->async.result = kmalloc(sizeof(*out->async.result), GFP_KERNEL);
+ if (unlikely(!out->async.result)) {
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ memset(out->async.result, 0, sizeof(*out->async.result));
+ init_completion(&out->async.result->completion);
+
+ out->async.request = ablkcipher_request_alloc(out->async.s, GFP_KERNEL);
+ if (unlikely(!out->async.request)) {
+ dprintk(1,KERN_ERR,"error allocating async crypto request\n");
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ ablkcipher_request_set_callback(out->async.request, CRYPTO_TFM_REQ_MAY_BACKLOG,
+ cryptodev_complete, out->async.result);
+
+ out->init = 1;
+ return 0;
+error:
+ if (out->async.request)
+ ablkcipher_request_free(out->async.request);
+ kfree(out->async.result);
+ if (out->async.s)
+ crypto_free_ablkcipher(out->async.s);
+
+ return ret;
+}
+
+void cryptodev_cipher_deinit(struct cipher_data* cdata)
+{
+ if (cdata->init) {
+ if (cdata->async.request)
+ ablkcipher_request_free(cdata->async.request);
+ kfree(cdata->async.result);
+ if (cdata->async.s)
+ crypto_free_ablkcipher(cdata->async.s);
+
+ cdata->init = 0;
+ }
+}
+
+void cryptodev_cipher_set_iv(struct cipher_data* cdata, void *iv, size_t iv_size)
+{
+ memcpy(cdata->async.iv, iv, min(iv_size,sizeof(cdata->async.iv)));
+}
+
+static inline int waitfor (struct cryptodev_result* cr, ssize_t ret)
+{
+ switch (ret) {
+ case 0:
+ break;
+ case -EINPROGRESS:
+ case -EBUSY:
+ wait_for_completion(&cr->completion);
+ /* At this point we known for sure the request has finished,
+ * because wait_for_completion above was not interruptible.
+ * This is important because otherwise hardware or driver
+ * might try to access memory which will be freed or reused for
+ * another request. */
+
+ if (unlikely(cr->err)) {
+ dprintk(0,KERN_ERR,"error from async request: %d \n", cr->err);
+ return cr->err;
+ }
+
+ break;
+ default:
+ return ret;
+ }
+
+ return 0;
+}
+
+
+int _cryptodev_cipher_encrypt(struct cipher_data* cdata, const void* plaintext,
+ size_t plaintext_size, void* ciphertext, size_t ciphertext_size)
+{
+struct scatterlist sg, sg2;
+
+ sg_init_one(&sg, plaintext, plaintext_size);
+ sg_init_one(&sg2, ciphertext, ciphertext_size);
+
+ return cryptodev_cipher_encrypt( cdata, &sg, &sg2, plaintext_size);
+}
+
+int _cryptodev_cipher_decrypt(struct cipher_data* cdata, const void* ciphertext,
+ size_t ciphertext_size, void* plaintext, size_t plaintext_size)
+{
+struct scatterlist sg, sg2;
+
+ sg_init_one(&sg, ciphertext, ciphertext_size);
+ sg_init_one(&sg2, plaintext, plaintext_size);
+
+ return cryptodev_cipher_decrypt( cdata, &sg, &sg2, ciphertext_size);
+}
+
+
+ssize_t cryptodev_cipher_encrypt( struct cipher_data* cdata, const struct scatterlist *sg1, struct scatterlist *sg2, size_t len)
+{
+ int ret;
+
+ INIT_COMPLETION(cdata->async.result->completion);
+ ablkcipher_request_set_crypt(cdata->async.request, (struct scatterlist*)sg1, sg2,
+ len, cdata->async.iv);
+ ret = crypto_ablkcipher_encrypt(cdata->async.request);
+
+ return waitfor(cdata->async.result,ret);
+}
+
+ssize_t cryptodev_cipher_decrypt( struct cipher_data* cdata, const struct scatterlist *sg1, struct scatterlist *sg2, size_t len)
+{
+ int ret;
+
+ INIT_COMPLETION(cdata->async.result->completion);
+ ablkcipher_request_set_crypt(cdata->async.request, (struct scatterlist*)sg1, sg2,
+ len, cdata->async.iv);
+ ret = crypto_ablkcipher_decrypt(cdata->async.request);
+
+ return waitfor(cdata->async.result, ret);
+}
+
+/* Hash functions */
+
+int cryptodev_hash_init( struct hash_data* hdata, const char* alg_name, int hmac_mode, void * mackey, size_t mackeylen)
+{
+int ret;
+
+ hdata->async.s = crypto_alloc_ahash(alg_name, 0, 0);
+ if (unlikely(IS_ERR(hdata->async.s))) {
+ dprintk(1,KERN_DEBUG,"%s: Failed to load transform for %s\n", __func__,
+ alg_name);
+ return -EINVAL;
+ }
+
+ /* Copy the key from user and set to TFM. */
+ if (hmac_mode != 0) {
+
+ ret = crypto_ahash_setkey(hdata->async.s, mackey, mackeylen);
+ if (unlikely(ret)) {
+ dprintk(1,KERN_DEBUG,"Setting hmac key failed for %s-%zu.\n",
+ alg_name, mackeylen*8);
+ ret = -EINVAL;
+ goto error;
+ }
+ }
+
+ hdata->digestsize = crypto_ahash_digestsize(hdata->async.s);
+
+ hdata->async.result = kmalloc(sizeof(*hdata->async.result), GFP_KERNEL);
+ if (unlikely(!hdata->async.result)) {
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ memset(hdata->async.result, 0, sizeof(*hdata->async.result));
+ init_completion(&hdata->async.result->completion);
+
+ hdata->async.request = ahash_request_alloc(hdata->async.s, GFP_KERNEL);
+ if (unlikely(!hdata->async.request)) {
+ dprintk(0,KERN_ERR,"error allocating async crypto request\n");
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ ahash_request_set_callback(hdata->async.request, CRYPTO_TFM_REQ_MAY_BACKLOG,
+ cryptodev_complete, hdata->async.result);
+
+ ret = crypto_ahash_init(hdata->async.request);
+ if (unlikely(ret)) {
+ dprintk(0,KERN_ERR,
+ "error in crypto_hash_init()\n");
+ goto error_request;
+ }
+
+ hdata->init = 1;
+ return 0;
+
+error_request:
+ ahash_request_free(hdata->async.request);
+error:
+ kfree(hdata->async.result);
+ crypto_free_ahash(hdata->async.s);
+ return ret;
+}
+
+void cryptodev_hash_deinit(struct hash_data* hdata)
+{
+ if (hdata->init) {
+ if (hdata->async.request)
+ ahash_request_free(hdata->async.request);
+ kfree(hdata->async.result);
+ if (hdata->async.s)
+ crypto_free_ahash(hdata->async.s);
+ hdata->init = 0;
+ }
+}
+
+int cryptodev_hash_reset( struct hash_data* hdata)
+{
+int ret;
+ ret = crypto_ahash_init(hdata->async.request);
+ if (unlikely(ret)) {
+ dprintk(0,KERN_ERR,
+ "error in crypto_hash_init()\n");
+ return ret;
+ }
+
+ return 0;
+
+}
+
+ssize_t cryptodev_hash_update( struct hash_data* hdata, struct scatterlist *sg, size_t len)
+{
+ int ret;
+
+ INIT_COMPLETION(hdata->async.result->completion);
+ ahash_request_set_crypt(hdata->async.request, sg, NULL,
+ len);
+
+ ret = crypto_ahash_update(hdata->async.request);
+
+ return waitfor(hdata->async.result,ret);
+}
+
+ssize_t _cryptodev_hash_update( struct hash_data* hdata, const void* data, size_t len)
+{
+struct scatterlist sg;
+
+ sg_init_one(&sg, data, len);
+
+ return cryptodev_hash_update( hdata, &sg, len);
+}
+
+int cryptodev_hash_final( struct hash_data* hdata, void* output)
+{
+ int ret;
+
+ INIT_COMPLETION(hdata->async.result->completion);
+ ahash_request_set_crypt(hdata->async.request, NULL, output, 0);
+
+ ret = crypto_ahash_final(hdata->async.request);
+
+ return waitfor(hdata->async.result,ret);
+}
diff --git a/crypto/userspace/cryptodev_main.c b/crypto/userspace/cryptodev_main.c
new file mode 100644
index 0000000..c6419f4
--- /dev/null
+++ b/crypto/userspace/cryptodev_main.c
@@ -0,0 +1,13 @@
+#include "cryptodev_int.h"
+#include "ncr-int.h"
+#include <linux/version.h>
+
+MODULE_AUTHOR("Nikos Mavrogiannopoulos <[email protected]>");
+MODULE_DESCRIPTION("CryptoDev driver");
+MODULE_LICENSE("GPL");
+
+/* ====== Module parameters ====== */
+
+int cryptodev_verbosity = 0;
+module_param(cryptodev_verbosity, int, 0644);
+MODULE_PARM_DESC(cryptodev_verbosity, "0: normal, 1: verbose, 2: debug");
--
1.7.2.1

2010-08-20 08:46:02

by Miloslav Trmac

[permalink] [raw]
Subject: [PATCH 18/19] Add ioctl handlers

Add ioctl and compat_ioctl handling. This is the only file that
directly accesses structured data from userspace (other files may access
unformated data such as cipher input or multiple-precision integers).

Also add the last operation, ncr_master_key_set.
---
crypto/userspace/ncr.c | 405 ++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 405 insertions(+), 0 deletions(-)

diff --git a/crypto/userspace/ncr.c b/crypto/userspace/ncr.c
index 9fb56ad..ee812ab 100644
--- a/crypto/userspace/ncr.c
+++ b/crypto/userspace/ncr.c
@@ -44,6 +44,411 @@
*/
struct key_item_st master_key;

+static struct mutex lists_ida_mutex;
+static DEFINE_IDA(lists_ida);
+
+struct ncr_lists *ncr_init_lists(void)
+{
+ struct ncr_lists *lst;
+
+ lst = kmalloc(sizeof(*lst), GFP_KERNEL);
+ if(!lst) {
+ err();
+ return NULL;
+ }
+
+ memset(lst, 0, sizeof(*lst));
+
+ mutex_init(&lists_ida_mutex);
+ mutex_lock(&lists_ida_mutex);
+ /* ida_pre_get() should preallocate enough, and, due to lists_ida_mutex,
+ nobody else can use the preallocated data. Therefore the loop
+ recommended in idr_get_new() documentation is not necessary. */
+ if (ida_pre_get(&lists_ida, GFP_KERNEL) == 0 ||
+ ida_get_new(&lists_ida, &lst->id) != 0) {
+ mutex_unlock(&lists_ida_mutex);
+ kfree(lst);
+ return NULL;
+ }
+ mutex_unlock(&lists_ida_mutex);
+
+ mutex_init(&lst->key_idr_mutex);
+ idr_init(&lst->key_idr);
+
+ mutex_init(&lst->session_idr_mutex);
+ idr_init(&lst->session_idr);
+
+ return lst;
+}
+
+void ncr_deinit_lists(struct ncr_lists *lst)
+{
+ if(lst) {
+ ncr_key_list_deinit(lst);
+ ncr_sessions_list_deinit(lst);
+
+ mutex_lock(&lists_ida_mutex);
+ ida_remove(&lists_ida, lst->id);
+ mutex_unlock(&lists_ida_mutex);
+
+ kfree(lst);
+ }
+}
+
+void ncr_master_key_reset(void)
+{
+ memset(&master_key, 0, sizeof(master_key));
+}
+
+static int ncr_master_key_set(const struct ncr_master_key_set *st,
+ struct nlattr *tb[])
+{
+struct audit_buffer *ab;
+int ret;
+
+ /* This will also cause auditing of the syscall, including information
+ about the process, and success/failure indication. Note that on
+ error the AUDIT_CRYPTO_STORAGE_KEY record will be empty. */
+ ab = audit_log_start(current->audit_context, GFP_KERNEL,
+ AUDIT_CRYPTO_STORAGE_KEY);
+
+ if (current_euid() != 0 && !capable(CAP_SYS_ADMIN)) {
+ err();
+ ret = -EPERM;
+ goto end;
+ }
+
+ if (st->key_size > sizeof(master_key.key.secret.data)) {
+ err();
+ ret = -EINVAL;
+ goto end;
+ }
+
+ if (st->key_size != 16 && st->key_size != 24 && st->key_size != 32) {
+ dprintk(0, KERN_DEBUG, "Master key size must be 16,24 or 32.\n");
+ ret = -EINVAL;
+ goto end;
+ }
+
+ if (master_key.type != NCR_KEY_TYPE_INVALID) {
+ dprintk(0, KERN_DEBUG, "Master key was previously initialized.\n");
+ }
+
+ if (unlikely(copy_from_user(master_key.key.secret.data, st->key,
+ st->key_size))) {
+ err();
+ ret = -EFAULT;
+ goto end;
+ }
+
+ dprintk(0, KERN_INFO, "Initializing master key.\n");
+ /* Not much we can reveal... */
+ audit_log_format(ab, "key_size=%u", (unsigned)st->key_size);
+
+ master_key.type = NCR_KEY_TYPE_SECRET;
+ master_key.key.secret.size = st->key_size;
+
+ ret = 0;
+
+end:
+ audit_log_end(ab);
+
+ return ret;
+}
+
+int
+ncr_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_)
+{
+ void __user *arg = (void __user *)arg_;
+ struct nlattr *tb[NCR_ATTR_MAX + 1];
+ void *attr_buf;
+ int ret;
+
+ if (unlikely(!lst))
+ BUG();
+
+ switch (cmd) {
+#define CASE_(LABEL, STRUCT, FUNCTION, ARGS) \
+ case (LABEL): { \
+ struct STRUCT data; \
+ \
+ attr_buf = NCR_GET_INPUT_ARGS_NO_OUTPUT(&data, tb, arg); \
+ if (IS_ERR(attr_buf)) { \
+ err(); \
+ return PTR_ERR(attr_buf); \
+ } \
+ ret = (FUNCTION)ARGS; \
+ break; \
+ }
+#define CASE_NO_OUTPUT(LABEL, STRUCT, FUNCTION) \
+ CASE_(LABEL, STRUCT, FUNCTION, (lst, &data, tb))
+#define CASE_NO_OUTPUT_COMPAT(LABEL, STRUCT, FUNCTION) \
+ CASE_(LABEL, STRUCT, FUNCTION, (lst, &data, tb, 0))
+
+ case NCRIO_KEY_INIT:
+ return ncr_key_init(lst);
+ CASE_NO_OUTPUT(NCRIO_KEY_GENERATE, ncr_key_generate, ncr_key_generate);
+ CASE_NO_OUTPUT(NCRIO_KEY_GENERATE_PAIR, ncr_key_generate_pair,
+ ncr_key_generate_pair);
+ CASE_NO_OUTPUT(NCRIO_KEY_DERIVE, ncr_key_derive, ncr_key_derive);
+ case NCRIO_KEY_GET_INFO: {
+ struct ncr_key_get_info data;
+ struct ncr_out out;
+
+ attr_buf = NCR_GET_INPUT_ARGS(&data, tb, arg);
+ if (IS_ERR(attr_buf)) {
+ err();
+ return PTR_ERR(attr_buf);
+ }
+ ret = NCR_OUT_INIT(&out, &data, arg);
+ if (ret != 0) {
+ err();
+ break;
+ }
+ ret = ncr_key_get_info(lst, &out, &data, tb);
+ ncr_out_free(&out);
+ break;
+ }
+ CASE_NO_OUTPUT(NCRIO_KEY_EXPORT, ncr_key_export, ncr_key_export);
+ CASE_NO_OUTPUT(NCRIO_KEY_IMPORT, ncr_key_import, ncr_key_import);
+ case NCRIO_KEY_DEINIT: {
+ ncr_key_t key;
+
+ ret = get_user(key, (const ncr_key_t __user *)arg);
+ if (unlikely(ret)) {
+ err();
+ return ret;
+ }
+ return ncr_key_deinit(lst, key);
+ }
+ CASE_NO_OUTPUT(NCRIO_KEY_WRAP, ncr_key_wrap, ncr_key_wrap);
+ CASE_NO_OUTPUT(NCRIO_KEY_UNWRAP, ncr_key_unwrap, ncr_key_unwrap);
+ CASE_NO_OUTPUT(NCRIO_KEY_STORAGE_WRAP, ncr_key_storage_wrap,
+ ncr_key_storage_wrap);
+ CASE_NO_OUTPUT(NCRIO_KEY_STORAGE_UNWRAP, ncr_key_storage_unwrap,
+ ncr_key_storage_unwrap);
+ CASE_NO_OUTPUT(NCRIO_SESSION_INIT, ncr_session_init, ncr_session_init);
+ CASE_NO_OUTPUT_COMPAT(NCRIO_SESSION_UPDATE, ncr_session_update,
+ ncr_session_update);
+ CASE_NO_OUTPUT_COMPAT(NCRIO_SESSION_FINAL, ncr_session_final,
+ ncr_session_final);
+ CASE_NO_OUTPUT_COMPAT(NCRIO_SESSION_ONCE, ncr_session_once,
+ ncr_session_once);
+ CASE_(NCRIO_MASTER_KEY_SET, ncr_master_key_set, ncr_master_key_set,
+ (&data, tb));
+ default:
+ return -EINVAL;
+#undef CASE_
+#undef CASE_NO_OUTPUT
+#undef CASE_NO_OUTPUT_COMPAT
+ }
+ kfree(attr_buf);
+ return ret;
+}
+
+#ifdef CONFIG_COMPAT
+struct compat_ncr_key_export {
+ __u32 input_size, output_size;
+ ncr_key_t key;
+ compat_uptr_t buffer;
+ compat_int_t buffer_size;
+ __NL_ATTRIBUTES;
+};
+#define COMPAT_NCRIO_KEY_EXPORT _IOWR('c', 209, struct compat_ncr_key_export)
+
+static void convert_ncr_key_export(struct ncr_key_export *new,
+ const struct compat_ncr_key_export *old)
+{
+ new->key = old->key;
+ new->buffer = compat_ptr(old->buffer);
+ new->buffer_size = old->buffer_size;
+}
+
+struct compat_ncr_key_import {
+ __u32 input_size, output_size;
+ ncr_key_t key;
+ compat_uptr_t data;
+ __u32 data_size;
+ __NL_ATTRIBUTES;
+};
+#define COMPAT_NCRIO_KEY_IMPORT _IOWR('c', 210, struct compat_ncr_key_import)
+
+static void convert_ncr_key_import(struct ncr_key_import *new,
+ const struct compat_ncr_key_import *old)
+{
+ new->key = old->key;
+ new->data = compat_ptr(old->data);
+ new->data_size = old->data_size;
+}
+
+struct compat_ncr_key_wrap {
+ __u32 input_size, output_size;
+ ncr_key_t wrapping_key;
+ ncr_key_t source_key;
+ compat_uptr_t buffer;
+ compat_int_t buffer_size;
+ __NL_ATTRIBUTES;
+};
+#define COMPAT_NCRIO_KEY_WRAP _IOWR('c', 250, struct compat_ncr_key_wrap)
+
+static void convert_ncr_key_wrap(struct ncr_key_wrap *new,
+ const struct compat_ncr_key_wrap *old)
+{
+ new->wrapping_key = old->wrapping_key;
+ new->source_key = old->source_key;
+ new->buffer = compat_ptr(old->buffer);
+ new->buffer_size = old->buffer_size;
+}
+
+struct compat_ncr_key_unwrap {
+ __u32 input_size, output_size;
+ ncr_key_t wrapping_key;
+ ncr_key_t dest_key;
+ compat_uptr_t data;
+ __u32 data_size;
+ __NL_ATTRIBUTES;
+};
+#define COMPAT_NCRIO_KEY_UNWRAP _IOWR('c', 251, struct compat_ncr_key_unwrap)
+
+static void convert_ncr_key_unwrap(struct ncr_key_unwrap *new,
+ const struct compat_ncr_key_unwrap *old)
+{
+ new->wrapping_key = old->wrapping_key;
+ new->dest_key = old->dest_key;
+ new->data = compat_ptr(old->data);
+ new->data_size = old->data_size;
+}
+
+struct compat_ncr_key_storage_wrap {
+ __u32 input_size, output_size;
+ ncr_key_t key;
+ compat_uptr_t buffer;
+ compat_int_t buffer_size;
+ __NL_ATTRIBUTES;
+};
+#define COMPAT_NCRIO_KEY_STORAGE_WRAP \
+ _IOWR('c', 261, struct compat_ncr_key_storage_wrap)
+
+static void convert_ncr_key_storage_wrap(struct ncr_key_storage_wrap *new,
+ const struct compat_ncr_key_storage_wrap *old)
+{
+ new->key = old->key;
+ new->buffer = compat_ptr(old->buffer);
+ new->buffer_size = old->buffer_size;
+}
+
+struct compat_ncr_key_storage_unwrap {
+ __u32 input_size, output_size;
+ ncr_key_t key;
+ compat_uptr_t data;
+ __u32 data_size;
+ __NL_ATTRIBUTES;
+};
+#define COMPAT_NCRIO_KEY_STORAGE_UNWRAP \
+ _IOWR('c', 262, struct compat_ncr_key_storage_wrap)
+
+static void convert_ncr_key_storage_unwrap(struct ncr_key_storage_unwrap *new,
+ const struct compat_ncr_key_storage_unwrap *old)
+{
+ new->key = old->key;
+ new->data = compat_ptr(old->data);
+ new->data_size = old->data_size;
+}
+
+struct compat_ncr_master_key_set {
+ __u32 input_size, output_size;
+ compat_uptr_t key;
+ __u32 key_size;
+ __NL_ATTRIBUTES;
+};
+#define COMPAT_NCRIO_MASTER_KEY_SET \
+ _IOWR('c', 260, struct compat_ncr_master_key_set)
+
+static void convert_ncr_master_key_set(struct ncr_master_key_set *new,
+ const struct compat_ncr_master_key_set *old)
+{
+ new->key = compat_ptr(old->key);
+ new->key_size = old->key_size;
+}
+
+long
+ncr_compat_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_)
+{
+ void __user *arg = (void __user *)arg_;
+ struct nlattr *tb[NCR_ATTR_MAX + 1];
+ void *attr_buf;
+ int ret;
+
+ if (unlikely(!lst))
+ BUG();
+
+ switch (cmd) {
+ case NCRIO_KEY_INIT:
+ case NCRIO_KEY_GENERATE:
+ case NCRIO_KEY_GENERATE_PAIR:
+ case NCRIO_KEY_DERIVE:
+ case NCRIO_KEY_GET_INFO:
+ case NCRIO_KEY_DEINIT:
+ case NCRIO_SESSION_INIT:
+ return ncr_ioctl(lst, cmd, arg_);
+
+#define CASE_(LABEL, STRUCT, FUNCTION, ARGS) \
+ case (LABEL): { \
+ struct compat_##STRUCT old; \
+ struct STRUCT new; \
+ \
+ attr_buf = NCR_GET_INPUT_ARGS_NO_OUTPUT(&old, tb, arg); \
+ if (IS_ERR(attr_buf)) { \
+ err(); \
+ return PTR_ERR(attr_buf); \
+ } \
+ convert_##STRUCT(&new, &old); \
+ ret = (FUNCTION)ARGS; \
+ break; \
+ }
+#define CASE_NO_OUTPUT(LABEL, STRUCT, FUNCTION) \
+ CASE_(LABEL, STRUCT, FUNCTION, (lst, &new, tb))
+
+#define CASE_COMPAT_ONLY(LABEL, STRUCT, FUNCTION) \
+ case (LABEL): { \
+ struct STRUCT data; \
+ \
+ attr_buf = NCR_GET_INPUT_ARGS_NO_OUTPUT(&data, tb, arg); \
+ if (IS_ERR(attr_buf)) { \
+ err(); \
+ return PTR_ERR(attr_buf); \
+ } \
+ ret = (FUNCTION)(lst, &data, tb, 1); \
+ break; \
+ }
+
+ CASE_NO_OUTPUT(COMPAT_NCRIO_KEY_EXPORT, ncr_key_export, ncr_key_export);
+ CASE_NO_OUTPUT(COMPAT_NCRIO_KEY_IMPORT, ncr_key_import, ncr_key_import);
+ CASE_NO_OUTPUT(COMPAT_NCRIO_KEY_WRAP, ncr_key_wrap, ncr_key_wrap);
+ CASE_NO_OUTPUT(COMPAT_NCRIO_KEY_UNWRAP, ncr_key_unwrap, ncr_key_unwrap);
+ CASE_NO_OUTPUT(COMPAT_NCRIO_KEY_STORAGE_WRAP, ncr_key_storage_wrap,
+ ncr_key_storage_wrap);
+ CASE_NO_OUTPUT(COMPAT_NCRIO_KEY_STORAGE_UNWRAP, ncr_key_storage_unwrap,
+ ncr_key_storage_unwrap);
+ CASE_COMPAT_ONLY(NCRIO_SESSION_UPDATE, ncr_session_update,
+ ncr_session_update);
+ CASE_COMPAT_ONLY(NCRIO_SESSION_FINAL, ncr_session_final,
+ ncr_session_final);
+ CASE_COMPAT_ONLY(NCRIO_SESSION_ONCE, ncr_session_once,
+ ncr_session_once);
+ CASE_(COMPAT_NCRIO_MASTER_KEY_SET, ncr_master_key_set,
+ ncr_master_key_set, (&new, tb));
+ default:
+ return -EINVAL;
+#undef CASE_
+#undef CASE_NO_OUTPUT
+#undef CASE_COMPAT_ONLY
+ }
+ kfree(attr_buf);
+ return ret;
+}
+#endif
+
int ncr_session_input_data_from_nla(struct ncr_session_input_data *dest,
const struct nlattr *nla, int compat)
{
--
1.7.2.1

2010-08-20 08:46:01

by Miloslav Trmac

[permalink] [raw]
Subject: [PATCH 17/19] Add session operations

This includes:
- ncr_session_init
- ncr_session_update
- ncr_session_final
- ncr_session_once

The ncr_session_*_from_nla() functions are separate from the main
session code because they belong into ncr.c along with other code that
deals directly with user-space data structures and handles
CONFIG_COMPAT.
---
crypto/userspace/ncr-sessions.c | 953 +++++++++++++++++++++++++++++++++++++++
crypto/userspace/ncr.c | 86 ++++
2 files changed, 1039 insertions(+), 0 deletions(-)

diff --git a/crypto/userspace/ncr-sessions.c b/crypto/userspace/ncr-sessions.c
index e6fd995..b2adb8b 100644
--- a/crypto/userspace/ncr-sessions.c
+++ b/crypto/userspace/ncr-sessions.c
@@ -32,6 +32,104 @@
#include <linux/scatterlist.h>
#include <net/netlink.h>

+static int _ncr_session_update_key(struct ncr_lists *lists, ncr_session_t ses,
+ struct nlattr *tb[]);
+static void _ncr_session_remove(struct ncr_lists *lst, ncr_session_t desc);
+
+static int session_list_deinit_fn(int id, void *item, void *unused)
+{
+ (void)unused;
+ _ncr_sessions_item_put(item);
+ return 0;
+}
+
+void ncr_sessions_list_deinit(struct ncr_lists *lst)
+{
+ /* The mutex is not necessary, but doesn't hurt and makes it easier to
+ verify locking correctness. */
+ mutex_lock(&lst->session_idr_mutex);
+ idr_for_each(&lst->session_idr, session_list_deinit_fn, NULL);
+ idr_remove_all(&lst->session_idr);
+ idr_destroy(&lst->session_idr);
+ mutex_unlock(&lst->session_idr_mutex);
+}
+
+/* returns the data item corresponding to desc */
+struct session_item_st* ncr_sessions_item_get(struct ncr_lists *lst, ncr_session_t desc)
+{
+struct session_item_st* item;
+
+ mutex_lock(&lst->session_idr_mutex);
+ item = idr_find(&lst->session_idr, desc);
+ if (item != NULL) {
+ atomic_inc(&item->refcnt);
+ mutex_unlock(&lst->session_idr_mutex);
+ return item;
+ }
+ mutex_unlock(&lst->session_idr_mutex);
+
+ err();
+ return NULL;
+}
+
+void _ncr_sessions_item_put( struct session_item_st* item)
+{
+ if (atomic_dec_and_test(&item->refcnt)) {
+ cryptodev_cipher_deinit(&item->cipher);
+ ncr_pk_cipher_deinit(&item->pk);
+ cryptodev_hash_deinit(&item->hash);
+ if (item->key)
+ _ncr_key_item_put(item->key);
+ kfree(item->sg);
+ kfree(item->pages);
+ kfree(item);
+ }
+}
+
+struct session_item_st* ncr_session_new(struct ncr_lists *lst)
+{
+ struct session_item_st* sess;
+
+ sess = kzalloc(sizeof(*sess), GFP_KERNEL);
+ if (sess == NULL) {
+ err();
+ return NULL;
+ }
+
+ sess->array_size = DEFAULT_PREALLOC_PAGES;
+ sess->pages = kzalloc(sess->array_size *
+ sizeof(struct page *), GFP_KERNEL);
+ sess->sg = kzalloc(sess->array_size *
+ sizeof(struct scatterlist), GFP_KERNEL);
+ if (sess->sg == NULL || sess->pages == NULL) {
+ err();
+ goto err_sess;
+ }
+ mutex_init(&sess->mem_mutex);
+
+ atomic_set(&sess->refcnt, 2); /* One for lst->list, one for "sess" */
+
+ mutex_lock(&lst->session_idr_mutex);
+ /* idr_pre_get() should preallocate enough, and, due to
+ session_idr_mutex, nobody else can use the preallocated data.
+ Therefore the loop recommended in idr_get_new() documentation is not
+ necessary. */
+ if (idr_pre_get(&lst->session_idr, GFP_KERNEL) == 0 ||
+ idr_get_new(&lst->session_idr, sess, &sess->desc) != 0) {
+ mutex_unlock(&lst->session_idr_mutex);
+ goto err_sess;
+ }
+ mutex_unlock(&lst->session_idr_mutex);
+
+ return sess;
+
+err_sess:
+ kfree(sess->sg);
+ kfree(sess->pages);
+ kfree(sess);
+ return NULL;
+}
+
static const struct algo_properties_st algo_properties[] = {
#define KSTR(x) .kstr = x, .kstr_len = sizeof(x) - 1
{ .algo = NCR_ALG_NULL, KSTR("ecb(cipher_null)"),
@@ -142,9 +240,864 @@ const struct algo_properties_st *_ncr_nla_to_properties(const struct nlattr *nla
return NULL;
}

+static const char *ncr_op_name(ncr_crypto_op_t op)
+{
+ static const char *const names[] = {
+ [NCR_OP_ENCRYPT] = "encrypt",
+ [NCR_OP_DECRYPT] = "decrypt",
+ [NCR_OP_SIGN] = "sign",
+ [NCR_OP_VERIFY] = "verify"
+ };
+
+ const char *res;
+
+ res = NULL;
+ if (op < ARRAY_SIZE(names))
+ res = names[op];
+ if (res == NULL)
+ res = "unknown";
+ return res;
+}
+
const char *ncr_algorithm_name(const struct algo_properties_st *algo)
{
if (algo != NULL && algo->kstr != NULL)
return algo->kstr;
return "unknown";
}
+
+static int key_item_get_nla_read(struct key_item_st **st,
+ struct ncr_lists *lists,
+ const struct nlattr *nla)
+{
+ int ret;
+
+ if (nla == NULL) {
+ err();
+ return -EINVAL;
+ }
+ ret = ncr_key_item_get_read(st, lists, nla_get_u32(nla));
+ if (ret < 0) {
+ err();
+ return ret;
+ }
+ return ret;
+}
+
+static int _ncr_session_init(struct ncr_lists *lists, ncr_crypto_op_t op,
+ struct nlattr *tb[])
+{
+ const struct nlattr *nla;
+ struct session_item_st* ns = NULL;
+ int ret, audit_ret;
+ const struct algo_properties_st *sign_hash;
+
+ ns = ncr_session_new(lists);
+ if (ns == NULL) {
+ err();
+ return -ENOMEM;
+ }
+
+ ns->op = op;
+ ns->algorithm = _ncr_nla_to_properties(tb[NCR_ATTR_ALGORITHM]);
+ if (ns->algorithm == NULL) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ switch(op) {
+ case NCR_OP_ENCRYPT:
+ case NCR_OP_DECRYPT:
+ if (!ns->algorithm->can_encrypt) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ /* read key */
+ ret = key_item_get_nla_read(&ns->key, lists,
+ tb[NCR_ATTR_KEY]);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+ if (ns->key->type == NCR_KEY_TYPE_SECRET) {
+ int keysize = ns->key->key.secret.size;
+
+ if (ns->algorithm->algo == NCR_ALG_NULL)
+ keysize = 0;
+
+ if (ns->algorithm->is_pk) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ ret = cryptodev_cipher_init(&ns->cipher, ns->algorithm->kstr,
+ ns->key->key.secret.data, keysize);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+
+ if (ns->algorithm->needs_iv) {
+ nla = tb[NCR_ATTR_IV];
+ if (nla == NULL) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+ cryptodev_cipher_set_iv(&ns->cipher,
+ nla_data(nla),
+ nla_len(nla));
+ }
+ } else if (ns->key->type == NCR_KEY_TYPE_PRIVATE || ns->key->type == NCR_KEY_TYPE_PUBLIC) {
+ ret = ncr_pk_cipher_init(ns->algorithm, &ns->pk,
+ tb, ns->key, NULL);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+ } else {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+ break;
+
+ case NCR_OP_SIGN:
+ case NCR_OP_VERIFY:
+ if (!ns->algorithm->can_sign && !ns->algorithm->can_digest) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ if (ns->algorithm->can_digest) {
+ if (ns->algorithm->is_pk) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ ret = cryptodev_hash_init(&ns->hash, ns->algorithm->kstr, 0, NULL, 0);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+
+ } else {
+ /* read key */
+ ret = key_item_get_nla_read(&ns->key, lists,
+ tb[NCR_ATTR_KEY]);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+
+ if (ns->algorithm->is_hmac && ns->key->type == NCR_KEY_TYPE_SECRET) {
+ if (ns->algorithm->is_pk) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ ret = cryptodev_hash_init(&ns->hash, ns->algorithm->kstr, 1,
+ ns->key->key.secret.data, ns->key->key.secret.size);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+
+ } else if (ns->algorithm->is_pk && (ns->key->type == NCR_KEY_TYPE_PRIVATE || ns->key->type == NCR_KEY_TYPE_PUBLIC)) {
+ nla = tb[NCR_ATTR_SIGNATURE_HASH_ALGORITHM];
+ sign_hash = _ncr_nla_to_properties(nla);
+ if (sign_hash == NULL) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ if (!sign_hash->can_digest) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ if (sign_hash->is_pk) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ ret = ncr_pk_cipher_init(ns->algorithm, &ns->pk,
+ tb, ns->key, sign_hash);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+
+ ret = cryptodev_hash_init(&ns->hash, sign_hash->kstr, 0, NULL, 0);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+ } else {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+ }
+
+ break;
+ default:
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ ret = ns->desc;
+
+fail:
+ // algorithm, params, op
+ audit_ret = audit_log_crypto_op(AUDIT_CRYPTO_OP_SESSION_INIT, lists->id,
+ ns->desc, ncr_op_name(ns->op),
+ ncr_algorithm_name(ns->algorithm),
+ ns->key != NULL ? ns->key->desc : -1,
+ ns->key != NULL ? ns->key->key_id : NULL,
+ ns->key != NULL ? ns->key->key_id_size : 0,
+ -1, NULL, 0);
+ if (audit_ret < 0 && ret == 0)
+ ret = audit_ret;
+ if (ret < 0) {
+ _ncr_session_remove(lists, ns->desc);
+ }
+ _ncr_sessions_item_put(ns);
+
+ return ret;
+}
+
+int ncr_session_init(struct ncr_lists *lists,
+ const struct ncr_session_init *session,
+ struct nlattr *tb[])
+{
+ return _ncr_session_init(lists, session->op, tb);
+}
+
+static int _ncr_session_encrypt(struct session_item_st* sess, const struct scatterlist* input, unsigned input_cnt,
+ size_t input_size, void *output, unsigned output_cnt, size_t *output_size)
+{
+int ret;
+
+ if (sess->algorithm->is_symmetric) {
+ /* read key */
+ ret = cryptodev_cipher_encrypt(&sess->cipher, input,
+ output, input_size);
+ if (ret < 0) {
+ err();
+ return ret;
+ }
+ /* FIXME: handle ciphers that do not require that */
+ *output_size = input_size;
+ } else { /* public key */
+ ret = ncr_pk_cipher_encrypt(&sess->pk, input, input_cnt, input_size,
+ output, output_cnt, output_size);
+
+ if (ret < 0) {
+ err();
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int _ncr_session_decrypt(struct session_item_st* sess, const struct scatterlist* input,
+ unsigned input_cnt, size_t input_size,
+ struct scatterlist *output, unsigned output_cnt, size_t *output_size)
+{
+int ret;
+
+ if (sess->algorithm->is_symmetric) {
+ /* read key */
+ ret = cryptodev_cipher_decrypt(&sess->cipher, input,
+ output, input_size);
+ if (ret < 0) {
+ err();
+ return ret;
+ }
+ /* FIXME: handle ciphers that do not require equality */
+ *output_size = input_size;
+ } else { /* public key */
+ ret = ncr_pk_cipher_decrypt(&sess->pk, input, input_cnt, input_size,
+ output, output_cnt, output_size);
+
+ if (ret < 0) {
+ err();
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static void _ncr_session_remove(struct ncr_lists *lst, ncr_session_t desc)
+{
+ struct session_item_st * item;
+
+ mutex_lock(&lst->session_idr_mutex);
+ item = idr_find(&lst->session_idr, desc);
+ if (item != NULL)
+ idr_remove(&lst->session_idr, desc); /* Steal the reference */
+ mutex_unlock(&lst->session_idr_mutex);
+
+ if (item != NULL)
+ _ncr_sessions_item_put(item);
+}
+
+static int _ncr_session_grow_pages(struct session_item_st *ses, int pagecount)
+{
+ struct scatterlist *sg;
+ struct page **pages;
+ int array_size;
+
+ if (likely(pagecount < ses->array_size))
+ return 0;
+
+ for (array_size = ses->array_size; array_size < pagecount;
+ array_size *= 2)
+ ;
+
+ dprintk(2, KERN_DEBUG, "%s: reallocating to %d elements\n",
+ __func__, array_size);
+ pages = krealloc(ses->pages, array_size * sizeof(struct page *),
+ GFP_KERNEL);
+ if (unlikely(pages == NULL))
+ return -ENOMEM;
+ ses->pages = pages;
+ sg = krealloc(ses->sg, array_size * sizeof(struct scatterlist),
+ GFP_KERNEL);
+ if (unlikely(sg == NULL))
+ return -ENOMEM;
+ ses->sg = sg;
+
+ ses->array_size = array_size;
+ return 0;
+}
+
+/* Make NCR_ATTR_UPDATE_INPUT_DATA and NCR_ATTR_UPDATE_OUTPUT_BUFFER available
+ in scatterlists */
+static int get_userbuf2(struct session_item_st *ses, struct nlattr *tb[],
+ struct scatterlist **src_sg, unsigned *src_cnt,
+ size_t *src_size, struct ncr_session_output_buffer *dst,
+ struct scatterlist **dst_sg, unsigned *dst_cnt,
+ int compat)
+{
+ const struct nlattr *src_nla, *dst_nla;
+ struct ncr_session_input_data src;
+ int src_pagecount, dst_pagecount = 0, pagecount, write_src = 1, ret;
+ size_t input_size;
+
+ src_nla = tb[NCR_ATTR_UPDATE_INPUT_DATA];
+ dst_nla = tb[NCR_ATTR_UPDATE_OUTPUT_BUFFER];
+
+ ret = ncr_session_input_data_from_nla(&src, src_nla, compat);
+ if (unlikely(ret != 0)) {
+ err();
+ return ret;
+ }
+ *src_size = src.data_size;
+
+ if (dst_nla != NULL) {
+ ret = ncr_session_output_buffer_from_nla(dst, dst_nla, compat);
+ if (unlikely(ret != 0)) {
+ err();
+ return ret;
+ }
+ }
+
+ input_size = src.data_size;
+ src_pagecount = PAGECOUNT(src.data, input_size);
+
+ if (dst_nla == NULL || src.data != dst->buffer) { /* non-in-situ transformation */
+ write_src = 0;
+ if (dst_nla != NULL) {
+ dst_pagecount = PAGECOUNT(dst->buffer,
+ dst->buffer_size);
+ } else {
+ dst_pagecount = 0;
+ }
+ } else {
+ src_pagecount = max((int)(PAGECOUNT(dst->buffer,
+ dst->buffer_size)),
+ src_pagecount);
+ input_size = max(input_size, dst->buffer_size);
+ }
+
+ pagecount = src_pagecount + dst_pagecount;
+ ret = _ncr_session_grow_pages(ses, pagecount);
+ if (ret != 0) {
+ err();
+ return ret;
+ }
+
+ if (__get_userbuf((void __user *)src.data, input_size, write_src,
+ src_pagecount, ses->pages, ses->sg)) {
+ err();
+ printk("write: %d\n", write_src);
+ return -EINVAL;
+ }
+ (*src_sg) = ses->sg;
+ *src_cnt = src_pagecount;
+
+ if (dst_pagecount) {
+ *dst_cnt = dst_pagecount;
+ (*dst_sg) = ses->sg + src_pagecount;
+
+ if (__get_userbuf(dst->buffer, dst->buffer_size, 1,
+ dst_pagecount, ses->pages + src_pagecount,
+ *dst_sg)) {
+ err();
+ release_user_pages(ses->pages, src_pagecount);
+ return -EINVAL;
+ }
+ } else {
+ if (dst_nla != NULL) {
+ *dst_cnt = src_pagecount;
+ (*dst_sg) = (*src_sg);
+ } else {
+ *dst_cnt = 0;
+ *dst_sg = NULL;
+ }
+ }
+
+ ses->available_pages = pagecount;
+
+ return 0;
+}
+
+/* Called when userspace buffers are used */
+static int _ncr_session_update(struct ncr_lists *lists, ncr_session_t ses,
+ struct nlattr *tb[], int compat)
+{
+ int ret;
+ struct session_item_st* sess;
+ struct scatterlist *isg = NULL;
+ struct scatterlist *osg = NULL;
+ unsigned osg_cnt=0, isg_cnt=0;
+ size_t isg_size = 0, osg_size;
+ struct ncr_session_output_buffer out;
+
+ sess = ncr_sessions_item_get(lists, ses);
+ if (sess == NULL) {
+ err();
+ return -EINVAL;
+ }
+
+ if (mutex_lock_interruptible(&sess->mem_mutex)) {
+ err();
+ _ncr_sessions_item_put(sess);
+ return -ERESTARTSYS;
+ }
+
+ ret = get_userbuf2(sess, tb, &isg, &isg_cnt, &isg_size, &out, &osg,
+ &osg_cnt, compat);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+
+ switch(sess->op) {
+ case NCR_OP_ENCRYPT:
+ if (osg == NULL) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ osg_size = out.buffer_size;
+ if (osg_size < isg_size) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ ret = _ncr_session_encrypt(sess, isg, isg_cnt, isg_size,
+ osg, osg_cnt, &osg_size);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+
+ ret = ncr_session_output_buffer_set_size(&out, osg_size,
+ compat);
+ if (ret != 0) {
+ err();
+ goto fail;
+ }
+ break;
+ case NCR_OP_DECRYPT:
+ if (osg == NULL) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ osg_size = out.buffer_size;
+ if (osg_size < isg_size) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ ret = _ncr_session_decrypt(sess, isg, isg_cnt, isg_size,
+ osg, osg_cnt, &osg_size);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+
+ ret = ncr_session_output_buffer_set_size(&out, osg_size,
+ compat);
+ if (ret != 0) {
+ err();
+ goto fail;
+ }
+ break;
+
+ case NCR_OP_SIGN:
+ case NCR_OP_VERIFY:
+ ret = cryptodev_hash_update(&sess->hash, isg, isg_size);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+ break;
+ default:
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ ret = 0;
+
+fail:
+ audit_log_crypto_op(AUDIT_CRYPTO_OP_SESSION_OP, lists->id, sess->desc,
+ ncr_op_name(sess->op),
+ ncr_algorithm_name(sess->algorithm), -1, NULL, 0,
+ -1, NULL, 0);
+
+ if (sess->available_pages) {
+ release_user_pages(sess->pages, sess->available_pages);
+ sess->available_pages = 0;
+ }
+ mutex_unlock(&sess->mem_mutex);
+ _ncr_sessions_item_put(sess);
+
+ return ret;
+}
+
+static int try_session_update(struct ncr_lists *lists, ncr_session_t ses,
+ struct nlattr *tb[], int compat)
+{
+ if (tb[NCR_ATTR_UPDATE_INPUT_KEY_AS_DATA] != NULL)
+ return _ncr_session_update_key(lists, ses, tb);
+ else if (tb[NCR_ATTR_UPDATE_INPUT_DATA] != NULL)
+ return _ncr_session_update(lists, ses, tb, compat);
+
+ return 0;
+}
+
+static int _ncr_session_final(struct ncr_lists *lists, ncr_session_t ses,
+ struct nlattr *tb[], int compat)
+{
+ const struct nlattr *nla;
+ int ret;
+ struct session_item_st* sess;
+ int digest_size;
+ uint8_t digest[NCR_HASH_MAX_OUTPUT_SIZE];
+ void *buffer = NULL;
+
+ sess = ncr_sessions_item_get(lists, ses);
+ if (sess == NULL) {
+ err();
+ return -EINVAL;
+ }
+
+ ret = try_session_update(lists, ses, tb, compat);
+ if (ret < 0) {
+ err();
+ _ncr_sessions_item_put(sess);
+ return ret;
+ }
+
+ if (mutex_lock_interruptible(&sess->mem_mutex)) {
+ err();
+ _ncr_sessions_item_put(sess);
+ return -ERESTARTSYS;
+ }
+
+ switch(sess->op) {
+ case NCR_OP_ENCRYPT:
+ case NCR_OP_DECRYPT:
+ break;
+ case NCR_OP_VERIFY: {
+ struct ncr_session_input_data src;
+
+ nla = tb[NCR_ATTR_FINAL_INPUT_DATA];
+ ret = ncr_session_input_data_from_nla(&src, nla, compat);
+ if (unlikely(ret != 0)) {
+ err();
+ goto fail;
+ }
+
+ buffer = kmalloc(src.data_size, GFP_KERNEL);
+ if (buffer == NULL) {
+ err();
+ ret = -ENOMEM;
+ goto fail;
+ }
+ if (unlikely(copy_from_user(buffer, src.data, src.data_size))) {
+ err();
+ ret = -EFAULT;
+ goto fail;
+ }
+
+ digest_size = sess->hash.digestsize;
+ if (digest_size == 0 || sizeof(digest) < digest_size) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+ ret = cryptodev_hash_final(&sess->hash, digest);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+
+ if (!sess->algorithm->is_pk)
+ ret = (digest_size == src.data_size
+ && memcmp(buffer, digest, digest_size) == 0);
+ else {
+ ret = ncr_pk_cipher_verify(&sess->pk, buffer,
+ src.data_size, digest,
+ digest_size);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+ }
+ break;
+ }
+
+ case NCR_OP_SIGN: {
+ struct ncr_session_output_buffer dst;
+ size_t output_size;
+
+ nla = tb[NCR_ATTR_FINAL_OUTPUT_BUFFER];
+ ret = ncr_session_output_buffer_from_nla(&dst, nla, compat);
+ if (unlikely(ret != 0)) {
+ err();
+ goto fail;
+ }
+
+ digest_size = sess->hash.digestsize;
+ if (digest_size == 0) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ ret = cryptodev_hash_final(&sess->hash, digest);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+
+ cryptodev_hash_deinit(&sess->hash);
+
+ if (!sess->algorithm->is_pk) {
+ if (dst.buffer_size < digest_size) {
+ err();
+ ret = -ERANGE;
+ goto fail;
+ }
+ if (unlikely(copy_to_user(dst.buffer, digest,
+ digest_size))) {
+ err();
+ ret = -EFAULT;
+ goto fail;
+ }
+ output_size = digest_size;
+ } else {
+ output_size = dst.buffer_size;
+ buffer = kmalloc(output_size, GFP_KERNEL);
+ if (buffer == NULL) {
+ err();
+ ret = -ENOMEM;
+ goto fail;
+ }
+ ret = ncr_pk_cipher_sign(&sess->pk, digest, digest_size,
+ buffer, &output_size);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+ if (unlikely(copy_to_user(dst.buffer, buffer,
+ output_size))) {
+ err();
+ ret = -EFAULT;
+ goto fail;
+ }
+ }
+
+ ret = ncr_session_output_buffer_set_size(&dst, output_size,
+ compat);
+ if (ret != 0) {
+ err();
+ goto fail;
+ }
+ break;
+ }
+ default:
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+fail:
+ audit_log_crypto_op(AUDIT_CRYPTO_OP_SESSION_FINAL, lists->id,
+ sess->desc, ncr_op_name(sess->op),
+ ncr_algorithm_name(sess->algorithm), -1, NULL, 0,
+ -1, NULL, 0);
+
+ kfree(buffer);
+ mutex_unlock(&sess->mem_mutex);
+
+ cryptodev_hash_deinit(&sess->hash);
+ if (sess->algorithm->is_symmetric) {
+ cryptodev_cipher_deinit(&sess->cipher);
+ } else {
+ ncr_pk_cipher_deinit(&sess->pk);
+ }
+
+ _ncr_sessions_item_put(sess);
+ _ncr_session_remove(lists, ses);
+
+ return ret;
+}
+
+/* Direct with key: Allows to hash a key */
+static int _ncr_session_update_key(struct ncr_lists *lists, ncr_session_t ses,
+ struct nlattr *tb[])
+{
+ int ret;
+ struct session_item_st* sess;
+ struct key_item_st* key = NULL;
+
+ sess = ncr_sessions_item_get(lists, ses);
+ if (sess == NULL) {
+ err();
+ return -EINVAL;
+ }
+
+ /* read key */
+ ret = key_item_get_nla_read(&key, lists,
+ tb[NCR_ATTR_UPDATE_INPUT_KEY_AS_DATA]);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+
+ if (key->type != NCR_KEY_TYPE_SECRET) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ switch(sess->op) {
+ case NCR_OP_ENCRYPT:
+ case NCR_OP_DECRYPT:
+ err();
+ ret = -EINVAL;
+ goto fail;
+ case NCR_OP_SIGN:
+ case NCR_OP_VERIFY:
+ ret = _cryptodev_hash_update(&sess->hash,
+ key->key.secret.data, key->key.secret.size);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+ break;
+ default:
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ ret = 0;
+
+fail:
+ audit_log_crypto_op(AUDIT_CRYPTO_OP_SESSION_OP, lists->id, sess->desc,
+ ncr_op_name(sess->op),
+ ncr_algorithm_name(sess->algorithm),
+ key != NULL ? key->desc : -1,
+ key != NULL ? key->key_id : NULL,
+ key != NULL ? key->key_id_size : 0, -1, NULL, 0);
+
+ if (key) _ncr_key_item_put(key);
+ _ncr_sessions_item_put(sess);
+
+ return ret;
+}
+
+int ncr_session_update(struct ncr_lists *lists,
+ const struct ncr_session_update *op, struct nlattr *tb[],
+ int compat)
+{
+ int ret;
+
+ if (tb[NCR_ATTR_UPDATE_INPUT_DATA] != NULL)
+ ret = _ncr_session_update(lists, op->ses, tb, compat);
+ else if (tb[NCR_ATTR_UPDATE_INPUT_KEY_AS_DATA] != NULL)
+ ret = _ncr_session_update_key(lists, op->ses, tb);
+ else
+ ret = -EINVAL;
+
+ if (unlikely(ret)) {
+ err();
+ return ret;
+ }
+
+ return 0;
+}
+
+int ncr_session_final(struct ncr_lists *lists,
+ const struct ncr_session_final *op, struct nlattr *tb[],
+ int compat)
+{
+ return _ncr_session_final(lists, op->ses, tb, compat);
+}
+
+int ncr_session_once(struct ncr_lists *lists,
+ const struct ncr_session_once *once, struct nlattr *tb[],
+ int compat)
+{
+ int ret;
+
+ ret = _ncr_session_init(lists, once->op, tb);
+ if (ret < 0) {
+ err();
+ return ret;
+ }
+
+ ret = _ncr_session_final(lists, ret, tb, compat);
+ if (ret < 0) {
+ err();
+ return ret;
+ }
+
+ return ret;
+}
diff --git a/crypto/userspace/ncr.c b/crypto/userspace/ncr.c
index 1838aab..9fb56ad 100644
--- a/crypto/userspace/ncr.c
+++ b/crypto/userspace/ncr.c
@@ -22,8 +22,94 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

+#include <linux/audit.h>
+#include <linux/compat.h>
+#include <linux/crypto.h>
+#include <linux/ioctl.h>
+#include <linux/mm.h>
+#include <linux/mutex.h>
+#include <linux/highmem.h>
+#include <linux/random.h>
+#include <linux/uaccess.h>
+#include <linux/scatterlist.h>
+#include <linux/cred.h>
+#include <linux/capability.h>
+#include <linux/ncr.h>
+#include <net/netlink.h>
#include "ncr-int.h"
+#include "utils.h"
+#include <linux/workqueue.h>

/* This is the master wrapping key for storage of keys
*/
struct key_item_st master_key;
+
+int ncr_session_input_data_from_nla(struct ncr_session_input_data *dest,
+ const struct nlattr *nla, int compat)
+{
+ if (unlikely(nla == NULL))
+ return -EINVAL;
+#ifdef CONFIG_COMPAT
+ if (!compat) {
+#endif
+ if (unlikely(nla_len(nla) < sizeof(dest)))
+ return -ERANGE; /* nla_validate would return -ERANGE. */
+ memcpy(dest, nla_data(nla), sizeof(*dest));
+#ifdef CONFIG_COMPAT
+ } else {
+ struct compat_ncr_session_input_data old;
+
+ if (unlikely(nla_len(nla) < sizeof(old)))
+ return -ERANGE;
+ memcpy(&old, nla_data(nla), sizeof(old));
+ dest->data = compat_ptr(old.data);
+ dest->data_size = old.data_size;
+ }
+#endif
+ return 0;
+}
+
+int ncr_session_output_buffer_from_nla(struct ncr_session_output_buffer *dest,
+ const struct nlattr *nla, int compat)
+{
+ if (unlikely(nla == NULL))
+ return -EINVAL;
+#ifdef CONFIG_COMPAT
+ if (!compat) {
+#endif
+ if (unlikely(nla_len(nla) < sizeof(dest)))
+ return -ERANGE; /* nla_validate would return -ERANGE. */
+ memcpy(dest, nla_data(nla), sizeof(*dest));
+#ifdef CONFIG_COMPAT
+ } else {
+ struct compat_ncr_session_output_buffer old;
+
+ if (unlikely(nla_len(nla) < sizeof(old)))
+ return -ERANGE;
+ memcpy(&old, nla_data(nla), sizeof(old));
+ dest->buffer = compat_ptr(old.buffer);
+ dest->buffer_size = old.buffer_size;
+ dest->result_size_ptr = compat_ptr(old.result_size_ptr);
+ }
+#endif
+ return 0;
+}
+
+
+int ncr_session_output_buffer_set_size(const struct ncr_session_output_buffer *dest,
+ size_t size, int compat)
+{
+#ifdef CONFIG_COMPAT
+ if (!compat)
+#endif
+ return put_user(size, dest->result_size_ptr);
+#ifdef CONFIG_COMPAT
+ else {
+ compat_size_t old;
+
+ old = size;
+ return put_user(old,
+ (compat_size_t __user *)dest->result_size_ptr);
+ }
+#endif
+}
--
1.7.2.1

2010-08-20 08:46:00

by Miloslav Trmac

[permalink] [raw]
Subject: [PATCH 16/19] Add helpers for zero-copy userspace access

---
crypto/userspace/cryptodev_main.c | 87 +++++++++++++++++++++++++++++++++++++
1 files changed, 87 insertions(+), 0 deletions(-)

diff --git a/crypto/userspace/cryptodev_main.c b/crypto/userspace/cryptodev_main.c
index c6419f4..a6712db 100644
--- a/crypto/userspace/cryptodev_main.c
+++ b/crypto/userspace/cryptodev_main.c
@@ -1,3 +1,46 @@
+/*
+ * Driver for /dev/crypto device (aka CryptoDev)
+ *
+ * Copyright (c) 2004 Michal Ludvig <[email protected]>, SuSE Labs
+ * Copyright (c) 2009,2010 Nikos Mavrogiannopoulos <[email protected]>
+ *
+ * This file is part of linux cryptodev.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/*
+ * Device /dev/crypto provides an interface for
+ * accessing kernel CryptoAPI algorithms (ciphers,
+ * hashes) from userspace programs.
+ *
+ * /dev/crypto interface was originally introduced in
+ * OpenBSD and this module attempts to keep the API.
+ *
+ */
+
+#include <linux/audit.h>
+#include <linux/crypto.h>
+#include <linux/mm.h>
+#include <linux/highmem.h>
+#include <linux/ioctl.h>
+#include <linux/random.h>
+#include <linux/syscalls.h>
+#include <linux/pagemap.h>
+#include <linux/uaccess.h>
+#include <linux/scatterlist.h>
#include "cryptodev_int.h"
#include "ncr-int.h"
#include <linux/version.h>
@@ -11,3 +54,47 @@ MODULE_LICENSE("GPL");
int cryptodev_verbosity = 0;
module_param(cryptodev_verbosity, int, 0644);
MODULE_PARM_DESC(cryptodev_verbosity, "0: normal, 1: verbose, 2: debug");
+
+/* ====== CryptoAPI ====== */
+
+void release_user_pages(struct page **pg, int pagecount)
+{
+ while (pagecount--) {
+ if (!PageReserved(pg[pagecount]))
+ SetPageDirty(pg[pagecount]);
+ page_cache_release(pg[pagecount]);
+ }
+}
+
+/* offset of buf in it's first page */
+#define PAGEOFFSET(buf) ((unsigned long)buf & ~PAGE_MASK)
+
+/* fetch the pages addr resides in into pg and initialise sg with them */
+int __get_userbuf(uint8_t __user *addr, uint32_t len, int write,
+ int pgcount, struct page **pg, struct scatterlist *sg)
+{
+ int ret, pglen, i = 0;
+ struct scatterlist *sgp;
+
+ down_write(&current->mm->mmap_sem);
+ ret = get_user_pages(current, current->mm,
+ (unsigned long)addr, pgcount, write, 0, pg, NULL);
+ up_write(&current->mm->mmap_sem);
+ if (ret != pgcount)
+ return -EINVAL;
+
+ sg_init_table(sg, pgcount);
+
+ pglen = min((ptrdiff_t)(PAGE_SIZE - PAGEOFFSET(addr)), (ptrdiff_t)len);
+ sg_set_page(sg, pg[i++], pglen, PAGEOFFSET(addr));
+
+ len -= pglen;
+ for (sgp = sg_next(sg); len; sgp = sg_next(sgp)) {
+ pglen = min((uint32_t)PAGE_SIZE, len);
+ sg_set_page(sgp, pg[i++], pglen, 0);
+ len -= pglen;
+ }
+ sg_mark_end(sg_last(sg, pgcount));
+ return 0;
+}
+
--
1.7.2.1

2010-08-20 08:46:43

by Miloslav Trmac

[permalink] [raw]
Subject: [PATCH 08/19] Add per-process and per-user limits

Right now only key objects, not crypto sessions, are limited.
---
crypto/userspace/Makefile | 2 +-
crypto/userspace/ncr-limits.c | 247 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 248 insertions(+), 1 deletions(-)
create mode 100644 crypto/userspace/ncr-limits.c

diff --git a/crypto/userspace/Makefile b/crypto/userspace/Makefile
index a37969b..3dfbc39 100644
--- a/crypto/userspace/Makefile
+++ b/crypto/userspace/Makefile
@@ -1,6 +1,6 @@
ccflags-y += -I$(src)/libtommath -I$(src)/libtomcrypt/headers -I$(src) -DLTC_SOURCE

-cryptodev-objs := cryptodev_main.o cryptodev_cipher.o utils.o
+cryptodev-objs := cryptodev_main.o cryptodev_cipher.o ncr-limits.o utils.o


obj-$(CONFIG_CRYPTO_USERSPACE) += cryptodev.o
diff --git a/crypto/userspace/ncr-limits.c b/crypto/userspace/ncr-limits.c
new file mode 100644
index 0000000..345cca7
--- /dev/null
+++ b/crypto/userspace/ncr-limits.c
@@ -0,0 +1,247 @@
+/*
+ * New driver for /dev/crypto device (aka CryptoDev)
+
+ * Copyright (c) 2010 Katholieke Universiteit Leuven
+ *
+ * Author: Nikos Mavrogiannopoulos <[email protected]>
+ *
+ * This file is part of linux cryptodev.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <linux/hash.h>
+#include <linux/mutex.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/ncr.h>
+#include <linux/slab.h>
+#include <linux/highmem.h>
+#include <linux/random.h>
+#include <asm/atomic.h>
+#include <linux/version.h>
+#include <linux/file.h>
+#include <linux/cred.h>
+#include "ncr-int.h"
+
+/* arbitrary now */
+static unsigned int max_per_user[] = {
+ [LIMIT_TYPE_KEY] = 128,
+};
+
+static unsigned int max_per_process[] = {
+ [LIMIT_TYPE_KEY] = 64,
+};
+
+struct limit_user_item_st {
+ struct hlist_node hlist;
+ uid_t uid;
+ atomic_t cnt[NUM_LIMIT_TYPES];
+};
+
+struct limit_process_item_st {
+ struct hlist_node hlist;
+ pid_t pid;
+ atomic_t cnt[NUM_LIMIT_TYPES];
+};
+
+static struct mutex user_limit_mutex;
+#define USER_LIMIT_HASH_BITS 7
+#define USER_LIMIT_TABLE_SIZE (1 << USER_LIMIT_HASH_BITS)
+static struct hlist_head user_limit_table[USER_LIMIT_TABLE_SIZE];
+
+static struct hlist_head *user_limit_hash(uid_t uid)
+{
+ return &user_limit_table[hash_long(uid, USER_LIMIT_HASH_BITS)];
+}
+
+static struct mutex process_limit_mutex;
+#define PROCESS_LIMIT_HASH_BITS 9
+#define PROCESS_LIMIT_TABLE_SIZE (1 << PROCESS_LIMIT_HASH_BITS)
+static struct hlist_head process_limit_table[PROCESS_LIMIT_TABLE_SIZE];
+
+static struct hlist_head *process_limit_hash(pid_t pid)
+{
+ return &process_limit_table[hash_long(pid, PROCESS_LIMIT_HASH_BITS)];
+}
+
+void ncr_limits_init(void)
+{
+ size_t i;
+
+ mutex_init(&user_limit_mutex);
+ for (i = 0; i < USER_LIMIT_TABLE_SIZE; i++)
+ INIT_HLIST_HEAD(&user_limit_table[i]);
+
+ mutex_init(&process_limit_mutex);
+ for (i = 0; i < PROCESS_LIMIT_TABLE_SIZE; i++)
+ INIT_HLIST_HEAD(&process_limit_table[i]);
+}
+
+void ncr_limits_deinit(void)
+{
+struct limit_process_item_st* pitem;
+struct limit_user_item_st* uitem;
+struct hlist_node *pos, *tmp;
+size_t i;
+
+ mutex_lock(&user_limit_mutex);
+ for (i = 0; i < USER_LIMIT_TABLE_SIZE; i++) {
+ hlist_for_each_entry_safe(uitem, pos, tmp, &user_limit_table[i],
+ hlist) {
+ hlist_del(&uitem->hlist);
+ kfree(uitem);
+ }
+ }
+ mutex_unlock(&user_limit_mutex);
+
+ mutex_lock(&process_limit_mutex);
+ for (i = 0; i < PROCESS_LIMIT_TABLE_SIZE; i++) {
+ hlist_for_each_entry_safe(pitem, pos, tmp,
+ &process_limit_table[i], hlist) {
+ hlist_del(&pitem->hlist);
+ kfree(pitem);
+ }
+ }
+ mutex_unlock(&process_limit_mutex);
+
+}
+
+int ncr_limits_add_and_check(uid_t uid, pid_t pid, limits_type_t type)
+{
+struct limit_process_item_st* pitem;
+struct limit_user_item_st* uitem;
+struct hlist_head *user_head, *process_head;
+struct hlist_node *pos;
+int add = 1;
+int ret;
+ BUG_ON(type >= NUM_LIMIT_TYPES);
+
+ user_head = user_limit_hash(uid);
+ mutex_lock(&user_limit_mutex);
+ hlist_for_each_entry(uitem, pos, user_head, hlist) {
+ if (uitem->uid == uid) {
+ add = 0;
+
+ if (atomic_add_unless(&uitem->cnt[type], 1, max_per_user[type])==0) {
+ err();
+ mutex_unlock(&user_limit_mutex);
+ return -EPERM;
+ }
+ break;
+ }
+ }
+
+ if (add) {
+ size_t i;
+
+ uitem = kmalloc( sizeof(*uitem), GFP_KERNEL);
+ if (uitem == NULL) {
+ err();
+ mutex_unlock(&user_limit_mutex);
+ return -ENOMEM;
+ }
+ uitem->uid = uid;
+ for (i = 0; i < NUM_LIMIT_TYPES; i++)
+ atomic_set(&uitem->cnt[i], 0);
+ atomic_set(&uitem->cnt[type], 1);
+
+ hlist_add_head(&uitem->hlist, user_head);
+ }
+ mutex_unlock(&user_limit_mutex);
+
+ add = 1;
+ /* check process limits */
+ process_head = process_limit_hash(uid);
+ mutex_lock(&process_limit_mutex);
+ hlist_for_each_entry(pitem, pos, process_head, hlist) {
+ if (pitem->pid == pid) {
+ add = 0;
+ if (atomic_add_unless(&pitem->cnt[type], 1, max_per_process[type])==0) {
+ err();
+ mutex_unlock(&process_limit_mutex);
+
+ ret = -EPERM;
+ goto restore_user;
+ }
+ break;
+ }
+ }
+
+
+ if (add) {
+ size_t i;
+
+ pitem = kmalloc(sizeof(*pitem), GFP_KERNEL);
+ if (pitem == NULL) {
+ err();
+ mutex_unlock(&process_limit_mutex);
+ ret = -ENOMEM;
+ goto restore_user;
+ }
+ pitem->pid = pid;
+ for (i = 0; i < NUM_LIMIT_TYPES; i++)
+ atomic_set(&pitem->cnt[i], 0);
+ atomic_set(&pitem->cnt[type], 1);
+
+ hlist_add_head(&pitem->hlist, process_head);
+ }
+ mutex_unlock(&process_limit_mutex);
+
+ return 0;
+
+restore_user:
+ mutex_lock(&user_limit_mutex);
+ hlist_for_each_entry(uitem, pos, user_head, hlist) {
+ if (uitem->uid == uid) {
+ atomic_dec(&uitem->cnt[type]);
+ break;
+ }
+ }
+ mutex_unlock(&user_limit_mutex);
+ return ret;
+}
+
+void ncr_limits_remove(uid_t uid, pid_t pid, limits_type_t type)
+{
+struct limit_process_item_st* pitem;
+struct limit_user_item_st* uitem;
+struct hlist_head *hhead;
+struct hlist_node *pos;
+
+ BUG_ON(type >= NUM_LIMIT_TYPES);
+ hhead = user_limit_hash(uid);
+ mutex_lock(&user_limit_mutex);
+ hlist_for_each_entry(uitem, pos, hhead, hlist) {
+ if (uitem->uid == uid) {
+ atomic_dec(&uitem->cnt[type]);
+ break;
+ }
+ }
+ mutex_unlock(&user_limit_mutex);
+
+ /* check process limits */
+ hhead = process_limit_hash(uid);
+ mutex_lock(&process_limit_mutex);
+ hlist_for_each_entry(pitem, pos, hhead, hlist) {
+ if (pitem->pid == pid) {
+ atomic_dec(&pitem->cnt[type]);
+ break;
+ }
+ }
+ mutex_unlock(&process_limit_mutex);
+
+ return;
+}
--
1.7.2.1

2010-08-20 08:46:57

by Miloslav Trmac

[permalink] [raw]
Subject: [PATCH 13/19] Add /dev/crypto auditing infrastructure

Posted separately for review on linux-audit
---
include/linux/audit.h | 38 ++++++++++++++
kernel/auditfilter.c | 2 +
kernel/auditsc.c | 136 +++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 176 insertions(+), 0 deletions(-)

diff --git a/include/linux/audit.h b/include/linux/audit.h
index 3c7a358..8faa4e0 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -122,6 +122,9 @@
#define AUDIT_MAC_UNLBL_STCADD 1416 /* NetLabel: add a static label */
#define AUDIT_MAC_UNLBL_STCDEL 1417 /* NetLabel: del a static label */

+#define AUDIT_CRYPTO_STORAGE_KEY 1600 /* Key storage key configured */
+#define AUDIT_CRYPTO_USERSPACE_OP 1601 /* User-space crypto operation */
+
#define AUDIT_FIRST_KERN_ANOM_MSG 1700
#define AUDIT_LAST_KERN_ANOM_MSG 1799
#define AUDIT_ANOM_PROMISCUOUS 1700 /* Device changed promiscuous mode */
@@ -207,6 +210,7 @@
#define AUDIT_OBJ_TYPE 21
#define AUDIT_OBJ_LEV_LOW 22
#define AUDIT_OBJ_LEV_HIGH 23
+#define AUDIT_CRYPTO_OP 24

/* These are ONLY useful when checking
* at syscall exit time (AUDIT_AT_EXIT). */
@@ -314,6 +318,20 @@ enum {
#define AUDIT_PERM_READ 4
#define AUDIT_PERM_ATTR 8

+#define AUDIT_CRYPTO_OP_CONTEXT_NEW 1
+#define AUDIT_CRYPTO_OP_CONTEXT_DEL 2
+#define AUDIT_CRYPTO_OP_SESSION_INIT 3
+#define AUDIT_CRYPTO_OP_SESSION_OP 4
+#define AUDIT_CRYPTO_OP_SESSION_FINAL 5
+#define AUDIT_CRYPTO_OP_KEY_IMPORT 6
+#define AUDIT_CRYPTO_OP_KEY_EXPORT 7
+#define AUDIT_CRYPTO_OP_KEY_WRAP 8
+#define AUDIT_CRYPTO_OP_KEY_UNWRAP 9
+#define AUDIT_CRYPTO_OP_KEY_GEN 10
+#define AUDIT_CRYPTO_OP_KEY_DERIVE 11
+#define AUDIT_CRYPTO_OP_KEY_ZEROIZE 12
+#define AUDIT_CRYPTO_OP_KEY_GET_INFO 13
+
struct audit_status {
__u32 mask; /* Bit mask for valid entries */
__u32 enabled; /* 1 = enabled, 0 = disabled */
@@ -479,6 +497,10 @@ extern int __audit_log_bprm_fcaps(struct linux_binprm *bprm,
const struct cred *new,
const struct cred *old);
extern void __audit_log_capset(pid_t pid, const struct cred *new, const struct cred *old);
+extern int __audit_log_crypto_op(int op, int context, int session,
+ const char *operation, const char *algorithm,
+ int key1, void *key1_id, size_t key1_id_size,
+ int key2, void *key2_id, size_t key2_id_size);

static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp)
{
@@ -532,6 +554,21 @@ static inline void audit_log_capset(pid_t pid, const struct cred *new,
__audit_log_capset(pid, new, old);
}

+static inline int audit_log_crypto_op(int op, int context, int session,
+ const char *operation,
+ const char *algorithm, int key1,
+ void *key1_id, size_t key1_id_size,
+ int key2, void *key2_id,
+ size_t key2_id_size)
+{
+ if (unlikely(!audit_dummy_context()))
+ return __audit_log_crypto_op(op, context, session, operation,
+ algorithm, key1, key1_id,
+ key1_id_size, key2, key2_id,
+ key2_id_size);
+ return 0;
+}
+
extern int audit_n_rules;
extern int audit_signals;
#else
@@ -565,6 +602,7 @@ extern int audit_signals;
#define audit_mq_getsetattr(d,s) ((void)0)
#define audit_log_bprm_fcaps(b, ncr, ocr) ({ 0; })
#define audit_log_capset(pid, ncr, ocr) ((void)0)
+#define audit_log_crypto_op(op, context, session, key1, key1_id, key1_id_size, key2, key2_id, key2_id_size) (0)
#define audit_ptrace(t) ((void)0)
#define audit_n_rules 0
#define audit_signals 0
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index a706040..a25a587 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -363,6 +363,7 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule)
case AUDIT_DEVMINOR:
case AUDIT_EXIT:
case AUDIT_SUCCESS:
+ case AUDIT_CRYPTO_OP:
/* bit ops are only useful on syscall args */
if (f->op == Audit_bitmask || f->op == Audit_bittest)
goto exit_free;
@@ -457,6 +458,7 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
case AUDIT_ARG1:
case AUDIT_ARG2:
case AUDIT_ARG3:
+ case AUDIT_CRYPTO_OP:
break;
case AUDIT_ARCH:
entry->rule.arch_f = f;
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index fc0f928..47c1cc4 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -50,6 +50,7 @@
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/mount.h>
+#include <linux/ncr.h>
#include <linux/socket.h>
#include <linux/mqueue.h>
#include <linux/audit.h>
@@ -157,6 +158,21 @@ struct audit_aux_data_capset {
struct audit_cap_data cap;
};

+struct audit_crypto_op {
+ struct list_head list;
+ int op;
+ int context;
+ int session;
+ const char *operation;
+ const char *algorithm;
+ int key1;
+ unsigned char key1_id[MAX_KEY_ID_SIZE];
+ size_t key1_id_size;
+ int key2;
+ unsigned char key2_id[MAX_KEY_ID_SIZE];
+ size_t key2_id_size;
+};
+
struct audit_tree_refs {
struct audit_tree_refs *next;
struct audit_chunk *c[31];
@@ -181,6 +197,7 @@ struct audit_context {
struct audit_context *previous; /* For nested syscalls */
struct audit_aux_data *aux;
struct audit_aux_data *aux_pids;
+ struct list_head crypto;
struct sockaddr_storage *sockaddr;
size_t sockaddr_len;
/* Save things to print about task_struct */
@@ -632,6 +649,18 @@ static int audit_filter_rules(struct task_struct *tsk,
case AUDIT_FILETYPE:
result = audit_match_filetype(ctx, f->val);
break;
+ case AUDIT_CRYPTO_OP:
+ if (ctx) {
+ struct audit_crypto_op *ax;
+
+ list_for_each_entry(ax, &ctx->crypto, list) {
+ result = audit_comparator(ax->op, f->op,
+ f->val);
+ if (result)
+ break;
+ }
+ }
+ break;
}

if (!result) {
@@ -827,6 +856,7 @@ static inline void audit_free_names(struct audit_context *context)
static inline void audit_free_aux(struct audit_context *context)
{
struct audit_aux_data *aux;
+ struct audit_crypto_op *crypto, *tmp;

while ((aux = context->aux)) {
context->aux = aux->next;
@@ -836,6 +866,10 @@ static inline void audit_free_aux(struct audit_context *context)
context->aux_pids = aux->next;
kfree(aux);
}
+ list_for_each_entry_safe(crypto, tmp, &context->crypto, list) {
+ list_del(&crypto->list);
+ kfree(crypto);
+ }
}

static inline void audit_zero_context(struct audit_context *context,
@@ -853,6 +887,7 @@ static inline struct audit_context *audit_alloc_context(enum audit_state state)
if (!(context = kmalloc(sizeof(*context), GFP_KERNEL)))
return NULL;
audit_zero_context(context, state);
+ INIT_LIST_HEAD(&context->crypto);
INIT_LIST_HEAD(&context->killed_trees);
return context;
}
@@ -1316,6 +1351,7 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
int i, call_panic = 0;
struct audit_buffer *ab;
struct audit_aux_data *aux;
+ struct audit_crypto_op *crypto;
const char *tty;

/* tsk == current */
@@ -1442,6 +1478,58 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
call_panic = 1;
}

+ list_for_each_entry(crypto, &context->crypto, list) {
+ static const char *const ops[] = {
+ [AUDIT_CRYPTO_OP_CONTEXT_NEW] = "context_new",
+ [AUDIT_CRYPTO_OP_CONTEXT_DEL] = "context_del",
+ [AUDIT_CRYPTO_OP_SESSION_INIT] = "session_init",
+ [AUDIT_CRYPTO_OP_SESSION_OP] = "session_op",
+ [AUDIT_CRYPTO_OP_SESSION_FINAL] = "session_final",
+ [AUDIT_CRYPTO_OP_KEY_IMPORT] = "key_import",
+ [AUDIT_CRYPTO_OP_KEY_EXPORT] = "key_export",
+ [AUDIT_CRYPTO_OP_KEY_WRAP] = "key_wrap",
+ [AUDIT_CRYPTO_OP_KEY_UNWRAP] = "key_unwrap",
+ [AUDIT_CRYPTO_OP_KEY_GEN] = "key_gen",
+ [AUDIT_CRYPTO_OP_KEY_DERIVE] = "key_derive",
+ [AUDIT_CRYPTO_OP_KEY_ZEROIZE] = "key_zeroize",
+ [AUDIT_CRYPTO_OP_KEY_GET_INFO] = "key_get_info",
+ };
+
+ ab = audit_log_start(context, GFP_KERNEL,
+ AUDIT_CRYPTO_USERSPACE_OP);
+ if (!ab)
+ continue;
+ if (crypto->op < ARRAY_SIZE(ops) && ops[crypto->op] != NULL)
+ audit_log_format(ab, "crypto_op=%s", ops[crypto->op]);
+ else
+ audit_log_format(ab, "crypto_op=%d", crypto->op);
+ audit_log_format(ab, " ctx=%d", crypto->context);
+ if (crypto->session != -1)
+ audit_log_format(ab, " session=%d", crypto->session);
+ if (crypto->operation != NULL)
+ audit_log_format(ab, " operation=%s",
+ crypto->operation);
+ if (crypto->algorithm != NULL)
+ audit_log_format(ab, " algo=%s", crypto->algorithm);
+ if (crypto->key1 != -1) {
+ audit_log_format(ab, " key1=%d", crypto->key1);
+ if (crypto->key1_id_size > 0) {
+ audit_log_format(ab, " key1_id=");
+ audit_log_n_untrustedstring(ab, crypto->key1_id,
+ crypto->key1_id_size);
+ }
+ }
+ if (crypto->key2 != -1) {
+ audit_log_format(ab, " key2=%d", crypto->key2);
+ if (crypto->key2_id_size > 0) {
+ audit_log_format(ab, " key2_id=");
+ audit_log_n_untrustedstring(ab, crypto->key2_id,
+ crypto->key2_id_size);
+ }
+ }
+ audit_log_end(ab);
+ }
+
if (context->target_pid &&
audit_log_pid_context(context, context->target_pid,
context->target_auid, context->target_uid,
@@ -2486,6 +2574,54 @@ void __audit_log_capset(pid_t pid,
}

/**
+ * __audit_log_crypto_op - store information about an user-space crypto op
+ * @op: AUDIT_CRYPTO_OP_*
+ * @context: user-space context ID
+ * @session: session ID within @context, or -1
+ * @operation: more detailed operation description, or NULL
+ * @algorithm: algorithm (crypto API transform) name, or NULL
+ * @key1: ID of key 1 within @context, or -1
+ * @key1_id: user-space ID of key 1 set from user-space if @key1 != -1
+ * @key1_id_size: Size of @key1_id
+ * @key2: ID of key 2 within @context, or -1
+ * @key2_id: user-space ID of key 2 set from user-space if @key2 != -1
+ * @key2_id_size: Size of @key2_id
+ */
+int __audit_log_crypto_op(int op, int context, int session,
+ const char *operation, const char *algorithm,
+ int key1, void *key1_id, size_t key1_id_size,
+ int key2, void *key2_id, size_t key2_id_size)
+{
+ struct audit_crypto_op *ax;
+ struct audit_context *ctx = current->audit_context;
+
+ ax = kmalloc(sizeof(*ax), GFP_KERNEL);
+ if (!ax)
+ return -ENOMEM;
+
+ ax->op = op;
+ ax->context = context;
+ ax->session = session;
+ ax->operation = operation;
+ ax->algorithm = algorithm;
+ ax->key1 = key1;
+ if (key1 != -1) {
+ ax->key1_id_size = min(key1_id_size, sizeof(ax->key1_id));
+ memcpy(ax->key1_id, key1_id, ax->key1_id_size);
+ } else
+ ax->key1_id_size = 0;
+ ax->key2 = key2;
+ if (key2 != -1) {
+ ax->key2_id_size = min(key2_id_size, sizeof(ax->key2_id));
+ memcpy(ax->key2_id, key2_id, ax->key2_id_size);
+ } else
+ ax->key2_id_size = 0;
+ list_add_tail(&ax->list, &ctx->crypto);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(__audit_log_crypto_op);
+
+/**
* audit_core_dumps - record information about processes that end abnormally
* @signr: signal value
*
--
1.7.2.1

2010-08-20 08:47:01

by Miloslav Trmac

[permalink] [raw]
Subject: [PATCH 15/19] Add key wrapping operations

This includes:
- ncr_key_wrap
- ncr_key_unwrap
- ncr_key_storage_wrap
- ncr_key_storage_unwrap
---
crypto/userspace/Makefile | 5 +-
crypto/userspace/ncr-key-storage.c | 136 +++++++
crypto/userspace/ncr-key-wrap.c | 763 ++++++++++++++++++++++++++++++++++++
crypto/userspace/ncr.c | 29 ++
4 files changed, 931 insertions(+), 2 deletions(-)
create mode 100644 crypto/userspace/ncr-key-storage.c
create mode 100644 crypto/userspace/ncr-key-wrap.c
create mode 100644 crypto/userspace/ncr.c

diff --git a/crypto/userspace/Makefile b/crypto/userspace/Makefile
index 454ed9d..689ee0d 100644
--- a/crypto/userspace/Makefile
+++ b/crypto/userspace/Makefile
@@ -63,8 +63,9 @@ TOMCRYPT_OBJECTS = libtomcrypt/misc/zeromem.o libtomcrypt/misc/crypt/crypt_argch
libtomcrypt/misc/pk_get_oid.o libtomcrypt/pk/asn1/der/x509/der_encode_subject_public_key_info.o \
libtomcrypt/pk/asn1/der/x509/der_decode_subject_public_key_info.o

-cryptodev-objs := cryptodev_main.o cryptodev_cipher.o ncr-key.o ncr-limits.o \
- ncr-pk.o ncr-sessions.o ncr-dh.o utils.o $(TOMMATH_OBJECTS) \
+cryptodev-objs := cryptodev_main.o cryptodev_cipher.o ncr.o \
+ ncr-key.o ncr-limits.o ncr-pk.o ncr-sessions.o ncr-dh.o \
+ ncr-key-wrap.o ncr-key-storage.o utils.o $(TOMMATH_OBJECTS) \
$(TOMCRYPT_OBJECTS)


diff --git a/crypto/userspace/ncr-key-storage.c b/crypto/userspace/ncr-key-storage.c
new file mode 100644
index 0000000..4d0cb87
--- /dev/null
+++ b/crypto/userspace/ncr-key-storage.c
@@ -0,0 +1,136 @@
+/*
+ * New driver for /dev/crypto device (aka CryptoDev)
+
+ * Copyright (c) 2010 Katholieke Universiteit Leuven
+ *
+ * Author: Nikos Mavrogiannopoulos <[email protected]>
+ *
+ * This file is part of linux cryptodev.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <linux/ioctl.h>
+#include <linux/mm.h>
+#include <linux/ncr.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/scatterlist.h>
+#include "ncr-int.h"
+#include "cryptodev_int.h"
+
+struct packed_key {
+ uint32_t version;
+ uint8_t type;
+ uint32_t flags;
+ uint8_t algorithm[32]; /* NUL-terminated */
+ uint8_t key_id[MAX_KEY_ID_SIZE];
+ uint8_t key_id_size;
+
+ uint8_t raw[KEY_DATA_MAX_SIZE];
+ uint32_t raw_size;
+} __attribute__((__packed__));
+
+#define THIS_VERSION 1
+
+int key_to_storage_data( uint8_t** sdata, size_t * sdata_size, const struct key_item_st *key)
+{
+ struct packed_key * pkey;
+ int ret;
+
+ pkey = kmalloc(sizeof(*pkey), GFP_KERNEL);
+ if (pkey == NULL) {
+ err();
+ return -ENOMEM;
+ }
+
+ pkey->version = THIS_VERSION;
+ pkey->type = key->type;
+ pkey->flags = key->flags;
+ BUG_ON(strlen(key->algorithm->kstr) > sizeof(pkey->algorithm) - 1);
+ strcpy(pkey->algorithm, key->algorithm->kstr);
+ pkey->key_id_size = key->key_id_size;
+ memcpy(pkey->key_id, key->key_id, key->key_id_size);
+
+ if (key->type == NCR_KEY_TYPE_SECRET) {
+ pkey->raw_size = key->key.secret.size;
+ memcpy(pkey->raw, key->key.secret.data, pkey->raw_size);
+ } else if (key->type == NCR_KEY_TYPE_PRIVATE || key->type == NCR_KEY_TYPE_PUBLIC) {
+ pkey->raw_size = sizeof(pkey->raw);
+ ret = ncr_pk_pack( key, pkey->raw, &pkey->raw_size);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+ } else {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ *sdata = (void*)pkey;
+ *sdata_size = sizeof(*pkey);
+
+ return 0;
+fail:
+ kfree(pkey);
+
+ return ret;
+}
+
+int key_from_storage_data(struct key_item_st* key, const void* data, size_t data_size)
+{
+ const struct packed_key * pkey = data;
+ int ret;
+
+ if (data_size != sizeof(*pkey) || pkey->version != THIS_VERSION
+ || memchr(pkey->algorithm, '\0', sizeof(pkey->algorithm)) == NULL
+ || pkey->key_id_size > MAX_KEY_ID_SIZE) {
+ err();
+ return -EINVAL;
+ }
+
+ key->type = pkey->type;
+ key->flags = pkey->flags;
+
+ key->algorithm = _ncr_algo_to_properties(pkey->algorithm);
+ if (key->algorithm == NULL) {
+ err();
+ return -EINVAL;
+ }
+ key->key_id_size = pkey->key_id_size;
+ memcpy(key->key_id, pkey->key_id, pkey->key_id_size);
+
+ if (key->type == NCR_KEY_TYPE_SECRET) {
+ if (pkey->raw_size > NCR_CIPHER_MAX_KEY_LEN) {
+ err();
+ return -EINVAL;
+ }
+ key->key.secret.size = pkey->raw_size;
+ memcpy(key->key.secret.data, pkey->raw, pkey->raw_size);
+ } else if (key->type == NCR_KEY_TYPE_PUBLIC
+ || key->type == NCR_KEY_TYPE_PRIVATE) {
+ ret = ncr_pk_unpack( key, pkey->raw, pkey->raw_size);
+ if (ret < 0) {
+ err();
+ return ret;
+ }
+ } else {
+ err();
+ return -EINVAL;
+ }
+
+ return 0;
+}
diff --git a/crypto/userspace/ncr-key-wrap.c b/crypto/userspace/ncr-key-wrap.c
new file mode 100644
index 0000000..df96a79
--- /dev/null
+++ b/crypto/userspace/ncr-key-wrap.c
@@ -0,0 +1,763 @@
+/*
+ * New driver for /dev/crypto device (aka CryptoDev)
+
+ * Copyright (c) 2010 Katholieke Universiteit Leuven
+ *
+ * Author: Nikos Mavrogiannopoulos <[email protected]>
+ *
+ * This file is part of linux cryptodev.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <linux/audit.h>
+#include <linux/ioctl.h>
+#include <linux/mm.h>
+#include <linux/ncr.h>
+#include <linux/slab.h>
+#include <linux/highmem.h>
+#include <linux/random.h>
+#include <linux/uaccess.h>
+#include <linux/scatterlist.h>
+#include <net/netlink.h>
+#include "ncr-int.h"
+#include "cryptodev_int.h"
+
+typedef uint8_t val64_t[8];
+
+static const val64_t initA = "\xA6\xA6\xA6\xA6\xA6\xA6\xA6\xA6";
+
+
+static void val64_xor( val64_t val, uint32_t x)
+{
+ val[7] ^= x & 0xff;
+ val[6] ^= (x >> 8) & 0xff;
+ val[5] ^= (x >> 16) & 0xff;
+ val[4] ^= (x >> 24) & 0xff;
+}
+
+static int rfc3394_wrap(val64_t *R, unsigned int n, struct cipher_data* ctx,
+ uint8_t* output, size_t *output_size, const uint8_t iv[8])
+{
+val64_t A;
+uint8_t aes_block[16];
+int i,j;
+
+ if (*output_size < (n+1)*8) {
+ err();
+ return -ERANGE;
+ }
+
+ memcpy(A, iv, 8);
+
+ for (i=0;i<6*n;i++) {
+ memcpy(aes_block, A, 8);
+ memcpy(&aes_block[8], R[0], 8);
+
+ _cryptodev_cipher_encrypt(ctx, aes_block, sizeof(aes_block),
+ aes_block, sizeof(aes_block));
+
+ memcpy(A, aes_block, 8); /* A = MSB64(AES(A^{t-1}|R_{1}^{t-1})) */
+ val64_xor(A, i+1); /* A ^= t */
+
+ for (j=0;j<n-1;j++)
+ memcpy(R[j], R[j+1], sizeof(R[j]));
+ memcpy(R[n-1], &aes_block[8], 8); /* R[n-1] = LSB64(AES(A^{t-1}|R_{1}^{t-1})) */
+ }
+
+ memcpy(output, A, sizeof(A));
+ for (j=0;j<n;j++)
+ memcpy(&output[(j+1)*8], R[j], 8);
+ *output_size = (n+1)*8;
+
+ return 0;
+}
+
+static int rfc3394_unwrap(const uint8_t *wrapped_key, val64_t R[], unsigned int n, val64_t A, struct cipher_data *ctx)
+{
+ int i, j;
+ uint8_t aes_block[16];
+
+ memcpy(A, wrapped_key, 8); /* A = C[0] */
+ for (i=0;i<n;i++)
+ memcpy(R[i], &wrapped_key[(i+1)*8], 8);
+
+ for (i=(6*n)-1;i>=0;i--) {
+ val64_xor(A, i+1);
+
+ memcpy(aes_block, A, 8);
+ memcpy(&aes_block[8], R[n-1], 8);
+
+ _cryptodev_cipher_decrypt(ctx, aes_block, sizeof(aes_block),
+ aes_block, sizeof(aes_block));
+
+ memcpy(A, aes_block, 8);
+
+ for (j=n-1;j>=1;j--)
+ memcpy(R[j], R[j-1], sizeof(R[j]));
+
+ memcpy(R[0], &aes_block[8], 8);
+ }
+
+ return 0;
+}
+
+#define RFC5649_IV "\xA6\x59\x59\xA6"
+static int _wrap_aes_rfc5649(void* kdata, size_t kdata_size, struct key_item_st* kek,
+ void* output, size_t* output_size, const void* _iv, size_t iv_size)
+{
+size_t n;
+int i, ret;
+struct cipher_data ctx;
+uint8_t iv[8];
+val64_t *R = NULL;
+
+ if (iv_size != 4) {
+ memcpy(iv, RFC5649_IV, 4);
+ } else {
+ memcpy(iv, _iv, 4);
+ }
+ iv_size = 8;
+ iv[4] = (kdata_size >> 24) & 0xff;
+ iv[5] = (kdata_size >> 16) & 0xff;
+ iv[6] = (kdata_size >> 8) & 0xff;
+ iv[7] = (kdata_size) & 0xff;
+
+ n = (kdata_size+7)/8;
+ if (n==1) { /* unimplemented */
+ err();
+ return -EINVAL;
+ }
+
+ ret = cryptodev_cipher_init(&ctx, "ecb(aes)", kek->key.secret.data, kek->key.secret.size);
+ if (ret < 0) {
+ err();
+ return ret;
+ }
+
+ R = kmalloc(n * sizeof (*R), GFP_KERNEL);
+ if (R == NULL) {
+ err();
+ ret = -ENOMEM;
+ goto cleanup;
+ }
+
+ /* R = P */
+ for (i=0;i<kdata_size;i++) {
+ R[i/8][i%8] = ((uint8_t*)kdata)[i];
+ }
+
+ for (;i<n*8;i++) {
+ R[i/8][i%8] = 0;
+ }
+
+ ret = rfc3394_wrap( R, n, &ctx, output, output_size, iv);
+ if (ret < 0) {
+ err();
+ goto cleanup;
+ }
+
+ ret = 0;
+
+cleanup:
+ kfree(R);
+ cryptodev_cipher_deinit(&ctx);
+
+ return ret;
+}
+
+static int _unwrap_aes_rfc5649(void* kdata, size_t *kdata_size, struct key_item_st* kek,
+ const void *wrapped_key, size_t wrapped_key_size, const void* _iv, size_t iv_size)
+{
+size_t n;
+int i, ret;
+struct cipher_data ctx;
+uint8_t iv[4];
+size_t size;
+val64_t *R = NULL, A;
+
+ if (iv_size != 4) {
+ memcpy(iv, RFC5649_IV, 4);
+ } else {
+ memcpy(iv, _iv, 4);
+ }
+ iv_size = 4;
+
+ ret = cryptodev_cipher_init(&ctx, "ecb(aes)", kek->key.secret.data, kek->key.secret.size);
+ if (ret < 0) {
+ err();
+ return ret;
+ }
+
+ if (wrapped_key_size % 8 != 0) {
+ err();
+ ret = -EINVAL;
+ goto cleanup;
+ }
+
+ n = wrapped_key_size/8 - 1;
+
+ if (*kdata_size < (n-1)*8) {
+ err();
+ ret = -EINVAL;
+ goto cleanup;
+ }
+
+ R = kmalloc(n * sizeof (*R), GFP_KERNEL);
+ if (R == NULL) {
+ err();
+ ret = -ENOMEM;
+ goto cleanup;
+ }
+
+ ret = rfc3394_unwrap(wrapped_key, R, n, A, &ctx);
+ if (ret < 0) {
+ err();
+ goto cleanup;
+ }
+
+ if (memcmp(A, iv, 4)!= 0) {
+ err();
+ ret = -EINVAL;
+ goto cleanup;
+ }
+
+ size = (A[4] << 24) | (A[5] << 16) | (A[6] << 8) | A[7];
+ if (size > n*8 || size < (n-1)*8 || *kdata_size < size) {
+ err();
+ ret = -EINVAL;
+ goto cleanup;
+ }
+
+ memset(kdata, 0, size);
+ *kdata_size = size;
+ for (i=0;i<size;i++) {
+ ((uint8_t*)kdata)[i] = R[i/8][i%8];
+ }
+
+ ret = 0;
+
+cleanup:
+ kfree(R);
+ cryptodev_cipher_deinit(&ctx);
+
+ return ret;
+}
+
+
+static int wrap_aes_rfc5649(struct key_item_st* tobewrapped, struct key_item_st *kek,
+ void* output, size_t* output_size, const void* iv, size_t iv_size)
+{
+ if (tobewrapped->type != NCR_KEY_TYPE_SECRET) {
+ err();
+ return -EINVAL;
+ }
+
+ return _wrap_aes_rfc5649(tobewrapped->key.secret.data, tobewrapped->key.secret.size,
+ kek, output, output_size, iv, iv_size);
+
+}
+
+static int unwrap_aes_rfc5649(struct key_item_st* output, struct key_item_st *kek,
+ void* wrapped, size_t wrapped_size, const void* iv, size_t iv_size)
+{
+ output->type = NCR_KEY_TYPE_SECRET;
+
+ return _unwrap_aes_rfc5649(output->key.secret.data, &output->key.secret.size, kek,
+ wrapped, wrapped_size, iv, iv_size);
+}
+
+
+/* Wraps using the RFC3394 way.
+ */
+static int wrap_aes(struct key_item_st* tobewrapped, struct key_item_st *kek,
+ void* output, size_t *output_size, const void* iv, size_t iv_size)
+{
+size_t key_size, n;
+uint8_t *raw_key;
+int i, ret;
+struct cipher_data ctx;
+val64_t *R = NULL;
+
+ if (tobewrapped->type != NCR_KEY_TYPE_SECRET) {
+ err();
+ return -EINVAL;
+ }
+
+ if (iv_size < sizeof(initA)) {
+ iv_size = sizeof(initA);
+ iv = initA;
+ }
+
+ ret = cryptodev_cipher_init(&ctx, "ecb(aes)", kek->key.secret.data, kek->key.secret.size);
+ if (ret < 0) {
+ err();
+ return ret;
+ }
+
+ raw_key = tobewrapped->key.secret.data;
+ key_size = tobewrapped->key.secret.size;
+
+ if (key_size % 8 != 0) {
+ err();
+ ret = -EINVAL;
+ goto cleanup;
+ }
+
+ n = key_size/8;
+
+
+ R = kmalloc(sizeof(*R)*n, GFP_KERNEL);
+ if (R == NULL) {
+ err();
+ ret = -ENOMEM;
+ goto cleanup;
+ }
+
+ /* R = P */
+ for (i=0;i<n;i++) {
+ memcpy(R[i], &raw_key[i*8], 8);
+ }
+
+ ret = rfc3394_wrap( R, n, &ctx, output, output_size, iv);
+ if (ret < 0) {
+ err();
+ goto cleanup;
+ }
+
+ ret = 0;
+
+cleanup:
+ kfree(R);
+ cryptodev_cipher_deinit(&ctx);
+
+ return ret;
+}
+
+#if 0
+/* for debugging */
+void print_val64(char* str, val64_t val)
+{
+ int i;
+ printk("%s: ",str);
+ for (i=0;i<8;i++)
+ printk("%.2x", val[i]);
+ printk("\n");
+
+}
+#endif
+
+static int unwrap_aes(struct key_item_st* output, struct key_item_st *kek,
+ void* wrapped_key, size_t wrapped_key_size, const void* iv, size_t iv_size)
+{
+size_t n;
+val64_t A;
+int i, ret;
+struct cipher_data ctx;
+val64_t * R = NULL;
+
+ if (iv_size < sizeof(initA)) {
+ iv_size = sizeof(initA);
+ iv = initA;
+ }
+
+ ret = cryptodev_cipher_init(&ctx, "ecb(aes)", kek->key.secret.data, kek->key.secret.size);
+ if (ret < 0) {
+ err();
+ return ret;
+ }
+
+ output->type = NCR_KEY_TYPE_SECRET;
+
+ if (wrapped_key_size % 8 != 0) {
+ err();
+ ret = -EINVAL;
+ goto cleanup;
+ }
+
+ n = wrapped_key_size/8 - 1;
+
+ if (NCR_CIPHER_MAX_KEY_LEN < (n-1)*8) {
+ err();
+ ret = -EINVAL;
+ goto cleanup;
+ }
+
+ R = kmalloc(sizeof(*R)*n, GFP_KERNEL);
+ if (R == NULL) {
+ err();
+ ret = -ENOMEM;
+ goto cleanup;
+ }
+
+ ret = rfc3394_unwrap(wrapped_key, R, n, A, &ctx);
+ if (ret < 0) {
+ err();
+ goto cleanup;
+ }
+
+ if (memcmp(A, iv, 8)!= 0) {
+ err();
+ ret = -EINVAL;
+ goto cleanup;
+ }
+
+ memset(&output->key, 0, sizeof(output->key));
+ for (i=0;i<n;i++) {
+ memcpy(&output->key.secret.data[i*8], R[i], sizeof(R[i]));
+ }
+ output->key.secret.size = n*8;
+ output->flags = NCR_KEY_FLAG_WRAPPABLE;
+ output->type = NCR_KEY_TYPE_SECRET;
+
+ ret = 0;
+
+cleanup:
+ kfree(R);
+ cryptodev_cipher_deinit(&ctx);
+
+ return ret;
+}
+
+static const char *ncr_wrap_name(struct nlattr *tb[])
+{
+ const struct nlattr *nla;
+
+ nla = tb[NCR_ATTR_WRAPPING_ALGORITHM];
+ if (nla != NULL)
+ return nla_data(nla);
+ return "unknown";
+}
+
+int ncr_key_wrap(struct ncr_lists *lst, const struct ncr_key_wrap *wrap,
+ struct nlattr *tb[])
+{
+const struct nlattr *nla;
+struct key_item_st* wkey = NULL;
+struct key_item_st* key = NULL;
+void* data = NULL;
+const void *iv;
+size_t data_size, iv_size;
+int ret;
+
+ if (wrap->buffer_size < 0) {
+ err();
+ return -EINVAL;
+ }
+
+ ret = ncr_key_item_get_read(&wkey, lst, wrap->source_key);
+ if (ret < 0) {
+ err();
+ return ret;
+ }
+
+ if (!(wkey->flags & NCR_KEY_FLAG_WRAPPABLE)) {
+ err();
+ ret = -EPERM;
+ goto fail;
+ }
+
+ ret = ncr_key_item_get_read(&key, lst, wrap->wrapping_key);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+
+ data_size = wrap->buffer_size;
+ data = kmalloc(data_size, GFP_KERNEL);
+ if (data == NULL) {
+ err();
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ nla = tb[NCR_ATTR_IV];
+ if (nla != NULL) {
+ iv = nla_data(nla);
+ iv_size = nla_len(nla);
+ } else {
+ iv = NULL;
+ iv_size = 0;
+ }
+
+ nla = tb[NCR_ATTR_WRAPPING_ALGORITHM];
+ if (nla == NULL) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+ if (nla_strcmp(nla, NCR_WALG_AES_RFC3394) == 0)
+ ret = wrap_aes(wkey, key, data, &data_size, iv, iv_size);
+ else if (nla_strcmp(nla, NCR_WALG_AES_RFC5649) == 0)
+ ret = wrap_aes_rfc5649(wkey, key, data, &data_size, iv,
+ iv_size);
+ else {
+ err();
+ ret = -EINVAL;
+ }
+
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+
+ ret = copy_to_user(wrap->buffer, data, data_size);
+ if (unlikely(ret)) {
+ ret = -EFAULT;
+ goto fail;
+ }
+
+ ret = data_size;
+
+fail:
+ audit_log_crypto_op(AUDIT_CRYPTO_OP_KEY_WRAP, lst->id, -1, NULL,
+ ncr_wrap_name(tb), wrap->wrapping_key,
+ key != NULL ? key->key_id : NULL,
+ key != NULL ? key->key_id_size : 0,
+ wrap->source_key,
+ wkey != NULL ? wkey->key_id : NULL,
+ wkey != NULL ? wkey->key_id_size : 0);
+
+ if (wkey != NULL) _ncr_key_item_put(wkey);
+ if (key != NULL) _ncr_key_item_put(key);
+ kfree(data);
+
+ return ret;
+}
+
+/* Unwraps keys. All keys unwrapped are not accessible by
+ * userspace.
+ */
+int ncr_key_unwrap(struct ncr_lists *lst, const struct ncr_key_unwrap *wrap,
+ struct nlattr *tb[])
+{
+const struct nlattr *nla;
+struct key_item_st* wkey = NULL;
+struct key_item_st* key = NULL;
+void* data = NULL;
+const void *iv;
+size_t data_size, iv_size;
+int ret;
+
+ ret = ncr_key_item_get_write(&wkey, lst, wrap->dest_key);
+ if (ret < 0) {
+ err();
+ return ret;
+ }
+
+ ret = ncr_key_item_get_read(&key, lst, wrap->wrapping_key);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+
+ data_size = wrap->data_size;
+ data = kmalloc(data_size, GFP_KERNEL);
+ if (data == NULL) {
+ err();
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ if (unlikely(copy_from_user(data, wrap->data, data_size))) {
+ err();
+ ret = -EFAULT;
+ goto fail;
+ }
+
+ nla = tb[NCR_ATTR_IV];
+ if (nla != NULL) {
+ iv = nla_data(nla);
+ iv_size = nla_len(nla);
+ } else {
+ iv = NULL;
+ iv_size = 0;
+ }
+
+ nla = tb[NCR_ATTR_WRAPPING_ALGORITHM];
+ if (nla == NULL) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+ if (nla_strcmp(nla, NCR_WALG_AES_RFC3394) == 0)
+ ret = unwrap_aes(wkey, key, data, data_size, iv, iv_size);
+ else if (nla_strcmp(nla, NCR_WALG_AES_RFC5649) == 0)
+ ret = unwrap_aes_rfc5649(wkey, key, data, data_size, iv,
+ iv_size);
+ else {
+ err();
+ ret = -EINVAL;
+ }
+
+fail:
+ audit_log_crypto_op(AUDIT_CRYPTO_OP_KEY_UNWRAP, lst->id, -1, NULL,
+ ncr_wrap_name(tb), wrap->wrapping_key,
+ key != NULL ? key->key_id : NULL,
+ key != NULL ? key->key_id_size : 0, wrap->dest_key,
+ wkey != NULL ? wkey->key_id : NULL,
+ wkey != NULL ? wkey->key_id_size : 0);
+
+ if (wkey != NULL) _ncr_key_item_put(wkey);
+ if (key != NULL) _ncr_key_item_put(key);
+ if (data != NULL) kfree(data);
+
+ return ret;
+}
+
+int ncr_key_storage_wrap(struct ncr_lists *lst,
+ const struct ncr_key_storage_wrap *wrap,
+ struct nlattr *tb[])
+{
+struct key_item_st* wkey = NULL;
+void* data = NULL;
+size_t data_size;
+uint8_t * sdata = NULL;
+size_t sdata_size = 0;
+int ret;
+
+ if (master_key.type != NCR_KEY_TYPE_SECRET) {
+ err();
+ return -ENOKEY;
+ }
+
+ if (wrap->buffer_size < 0) {
+ err();
+ return -EINVAL;
+ }
+
+ ret = ncr_key_item_get_read(&wkey, lst, wrap->key);
+ if (ret < 0) {
+ err();
+ return ret;
+ }
+
+ if (!(wkey->flags & NCR_KEY_FLAG_WRAPPABLE)) {
+ err();
+ ret = -EPERM;
+ goto fail;
+ }
+
+ data_size = wrap->buffer_size;
+ data = kmalloc(data_size, GFP_KERNEL);
+ if (data == NULL) {
+ err();
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ ret = key_to_storage_data(&sdata, &sdata_size, wkey);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+
+ ret = _wrap_aes_rfc5649(sdata, sdata_size, &master_key, data, &data_size, NULL, 0);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+
+ ret = copy_to_user(wrap->buffer, data, data_size);
+ if (unlikely(ret)) {
+ ret = -EFAULT;
+ goto fail;
+ }
+
+ ret = data_size;
+
+fail:
+ audit_log_crypto_op(AUDIT_CRYPTO_OP_KEY_WRAP, lst->id, -1, NULL, NULL,
+ -1, NULL, 0, wrap->key,
+ wkey != NULL ? wkey->key_id : NULL,
+ wkey != NULL ? wkey->key_id_size : 0);
+
+ if (wkey != NULL) _ncr_key_item_put(wkey);
+ if (data != NULL) kfree(data);
+ if (sdata != NULL) kfree(sdata);
+
+ return ret;
+}
+
+int ncr_key_storage_unwrap(struct ncr_lists *lst,
+ const struct ncr_key_storage_unwrap *wrap,
+ struct nlattr *tb[])
+{
+struct key_item_st* wkey = NULL;
+void* data = NULL;
+uint8_t * sdata = NULL;
+size_t sdata_size = 0, data_size;
+int ret;
+
+ if (master_key.type != NCR_KEY_TYPE_SECRET) {
+ err();
+ return -ENOKEY;
+ }
+
+ ret = ncr_key_item_get_write(&wkey, lst, wrap->key);
+ if (ret < 0) {
+ err();
+ return ret;
+ }
+
+ data_size = wrap->data_size;
+ data = kmalloc(data_size, GFP_KERNEL);
+ if (data == NULL) {
+ err();
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ if (unlikely(copy_from_user(data, wrap->data, data_size))) {
+ err();
+ ret = -EFAULT;
+ goto fail;
+ }
+
+ sdata_size = data_size;
+ sdata = kmalloc(sdata_size, GFP_KERNEL);
+ if (sdata == NULL) {
+ err();
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ wkey->flags = NCR_KEY_FLAG_WRAPPABLE;
+
+ ret = _unwrap_aes_rfc5649(sdata, &sdata_size, &master_key, data, data_size, NULL, 0);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+
+ ret = key_from_storage_data(wkey, sdata, sdata_size);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+
+
+fail:
+ audit_log_crypto_op(AUDIT_CRYPTO_OP_KEY_UNWRAP, lst->id, -1, NULL, NULL,
+ -1, NULL, 0, wrap->key,
+ wkey != NULL ? wkey->key_id : NULL,
+ wkey != NULL ? wkey->key_id_size : 0);
+
+ if (wkey != NULL) _ncr_key_item_put(wkey);
+ if (data != NULL) kfree(data);
+ if (sdata != NULL) kfree(sdata);
+
+ return ret;
+}
diff --git a/crypto/userspace/ncr.c b/crypto/userspace/ncr.c
new file mode 100644
index 0000000..1838aab
--- /dev/null
+++ b/crypto/userspace/ncr.c
@@ -0,0 +1,29 @@
+/*
+ * New driver for /dev/crypto device (aka CryptoDev)
+ *
+ * Copyright (c) 2010 Katholieke Universiteit Leuven
+ *
+ * Author: Nikos Mavrogiannopoulos <[email protected]>
+ *
+ * This file is part of linux cryptodev.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "ncr-int.h"
+
+/* This is the master wrapping key for storage of keys
+ */
+struct key_item_st master_key;
--
1.7.2.1

2010-08-20 08:46:59

by Miloslav Trmac

[permalink] [raw]
Subject: [PATCH 14/19] Add most operations on key objects.

This includes:
- ncr_key_init
- ncr_key_deinit
- ncr_key_export (as plaintext)
- ncr_key_import
- ncr_key_generate
- ncr_key_generate_pair
- ncr_key_derive
- ncr_key_get_info
and supporting infrastructure.
---
crypto/userspace/Makefile | 2 +-
crypto/userspace/ncr-key.c | 689 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 690 insertions(+), 1 deletions(-)
create mode 100644 crypto/userspace/ncr-key.c

diff --git a/crypto/userspace/Makefile b/crypto/userspace/Makefile
index fa4168d..454ed9d 100644
--- a/crypto/userspace/Makefile
+++ b/crypto/userspace/Makefile
@@ -63,7 +63,7 @@ TOMCRYPT_OBJECTS = libtomcrypt/misc/zeromem.o libtomcrypt/misc/crypt/crypt_argch
libtomcrypt/misc/pk_get_oid.o libtomcrypt/pk/asn1/der/x509/der_encode_subject_public_key_info.o \
libtomcrypt/pk/asn1/der/x509/der_decode_subject_public_key_info.o

-cryptodev-objs := cryptodev_main.o cryptodev_cipher.o ncr-limits.o \
+cryptodev-objs := cryptodev_main.o cryptodev_cipher.o ncr-key.o ncr-limits.o \
ncr-pk.o ncr-sessions.o ncr-dh.o utils.o $(TOMMATH_OBJECTS) \
$(TOMCRYPT_OBJECTS)

diff --git a/crypto/userspace/ncr-key.c b/crypto/userspace/ncr-key.c
new file mode 100644
index 0000000..b90a4fc
--- /dev/null
+++ b/crypto/userspace/ncr-key.c
@@ -0,0 +1,689 @@
+/*
+ * New driver for /dev/crypto device (aka CryptoDev)
+ *
+ * Copyright (c) 2010 Katholieke Universiteit Leuven
+ *
+ * Author: Nikos Mavrogiannopoulos <[email protected]>
+ *
+ * This file is part of linux cryptodev.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <linux/audit.h>
+#include <linux/ioctl.h>
+#include <linux/mm.h>
+#include <linux/ncr.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/uaccess.h>
+#include <linux/scatterlist.h>
+#include <net/netlink.h>
+#include "ncr-int.h"
+#include "utils.h"
+
+static void ncr_key_clear(struct key_item_st* item);
+
+static int key_list_deinit_fn(int id, void *item, void *unused)
+{
+ (void)unused;
+ _ncr_key_item_put(item);
+ return 0;
+}
+
+void ncr_key_list_deinit(struct ncr_lists *lst)
+{
+ /* The mutex is not necessary, but doesn't hurt and makes it easier to
+ verify locking correctness. */
+ mutex_lock(&lst->key_idr_mutex);
+ idr_for_each(&lst->key_idr, key_list_deinit_fn, NULL);
+ idr_remove_all(&lst->key_idr);
+ idr_destroy(&lst->key_idr);
+ mutex_unlock(&lst->key_idr_mutex);
+}
+
+/* returns the data item corresponding to desc */
+int ncr_key_item_get_read(struct key_item_st**st, struct ncr_lists *lst,
+ ncr_key_t desc)
+{
+struct key_item_st* item;
+int ret;
+
+ *st = NULL;
+
+ mutex_lock(&lst->key_idr_mutex);
+ item = idr_find(&lst->key_idr, desc);
+ if (item == NULL) {
+ err();
+ ret = -EINVAL;
+ goto exit;
+ }
+ atomic_inc(&item->refcnt);
+
+ if (atomic_read(&item->writer) != 0) {
+ /* writer in place busy */
+ atomic_dec(&item->refcnt);
+ ret = -EBUSY;
+ goto exit;
+ }
+
+ *st = item;
+ ret = 0;
+
+exit:
+ mutex_unlock(&lst->key_idr_mutex);
+ return ret;
+}
+
+/* as above but will never return anything that
+ * is in use.
+ */
+int ncr_key_item_get_write( struct key_item_st** st,
+ struct ncr_lists *lst, ncr_key_t desc)
+{
+struct key_item_st* item;
+int ret;
+
+ *st = NULL;
+
+ mutex_lock(&lst->key_idr_mutex);
+ item = idr_find(&lst->key_idr, desc);
+ if (item == NULL) {
+ err();
+ ret = -EINVAL;
+ goto exit;
+ }
+ /* do not return items that are in use already */
+
+ if (atomic_add_unless(&item->writer, 1, 1)==0) {
+ /* another writer so busy */
+ ret = -EBUSY;
+ goto exit;
+ }
+
+ if (atomic_add_unless(&item->refcnt, 1, 2)==0) {
+ /* some reader is active so busy */
+ atomic_dec(&item->writer);
+ ret = -EBUSY;
+ goto exit;
+ }
+
+ *st = item;
+ ret = 0;
+
+exit:
+ mutex_unlock(&lst->key_idr_mutex);
+ return ret;
+}
+
+void _ncr_key_item_put( struct key_item_st* item)
+{
+ if (atomic_read(&item->writer) > 0)
+ atomic_dec(&item->writer);
+ if (atomic_dec_and_test(&item->refcnt)) {
+ ncr_limits_remove(item->uid, item->pid, LIMIT_TYPE_KEY);
+ ncr_key_clear(item);
+ kfree(item);
+ }
+}
+
+static void _ncr_key_remove(struct ncr_lists *lst, ncr_key_t desc)
+{
+ struct key_item_st * item;
+
+ mutex_lock(&lst->key_idr_mutex);
+ item = idr_find(&lst->key_idr, desc);
+ if (item != NULL)
+ idr_remove(&lst->key_idr, desc); /* Steal the reference */
+ mutex_unlock(&lst->key_idr_mutex);
+
+ if (item != NULL)
+ _ncr_key_item_put(item);
+}
+
+int ncr_key_init(struct ncr_lists *lst)
+{
+ ncr_key_t desc;
+ struct key_item_st* key;
+ int ret;
+
+ ret = ncr_limits_add_and_check(current_euid(), task_pid_nr(current), LIMIT_TYPE_KEY);
+ if (ret < 0) {
+ err();
+ return ret;
+ }
+
+ key = kmalloc(sizeof(*key), GFP_KERNEL);
+ if (key == NULL) {
+ err();
+ ret = -ENOMEM;
+ goto err_limits;
+ }
+
+ memset(key, 0, sizeof(*key));
+
+ atomic_set(&key->refcnt, 1);
+ atomic_set(&key->writer, 0);
+ key->uid = current_euid();
+ key->pid = task_pid_nr(current);
+ key->context_id = lst->id;
+
+ mutex_lock(&lst->key_idr_mutex);
+ /* idr_pre_get() should preallocate enough, and, due to key_idr_mutex,
+ nobody else can use the preallocated data. Therefore the loop
+ recommended in idr_get_new() documentation is not necessary. */
+ if (idr_pre_get(&lst->key_idr, GFP_KERNEL) == 0 ||
+ idr_get_new(&lst->key_idr, key, &key->desc) != 0) {
+ mutex_unlock(&lst->key_idr_mutex);
+ _ncr_key_item_put(key);
+ return -ENOMEM;
+ }
+ desc = key->desc;
+ mutex_unlock(&lst->key_idr_mutex);
+
+ return desc;
+
+err_limits:
+ ncr_limits_remove(current_euid(), task_pid_nr(current), LIMIT_TYPE_KEY);
+ return ret;
+}
+
+int ncr_key_deinit(struct ncr_lists *lst, ncr_key_t desc)
+{
+ _ncr_key_remove(lst, desc);
+ return 0;
+}
+
+int ncr_key_export(struct ncr_lists *lst, const struct ncr_key_export *data,
+ struct nlattr *tb[])
+{
+struct key_item_st* item = NULL;
+void* tmp = NULL;
+uint32_t tmp_size;
+int ret;
+
+ if (data->buffer_size < 0) {
+ err();
+ return -EINVAL;
+ }
+
+ ret = ncr_key_item_get_read(&item, lst, data->key);
+ if (ret < 0) {
+ err();
+ return ret;
+ }
+
+ if (!(item->flags & NCR_KEY_FLAG_EXPORTABLE)) {
+ err();
+ ret = -EPERM;
+ goto fail;
+ }
+
+ switch (item->type) {
+ case NCR_KEY_TYPE_SECRET:
+ if (item->key.secret.size > data->buffer_size) {
+ err();
+ ret = -ERANGE;
+ goto fail;
+ }
+
+ /* found */
+ if (item->key.secret.size > 0) {
+ ret = copy_to_user(data->buffer, item->key.secret.data, item->key.secret.size);
+ if (unlikely(ret)) {
+ err();
+ ret = -EFAULT;
+ goto fail;
+ }
+ }
+
+ ret = item->key.secret.size;
+ break;
+ case NCR_KEY_TYPE_PUBLIC:
+ case NCR_KEY_TYPE_PRIVATE:
+ tmp_size = data->buffer_size;
+
+ tmp = kmalloc(tmp_size, GFP_KERNEL);
+ if (tmp == NULL) {
+ err();
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ ret = ncr_pk_pack(item, tmp, &tmp_size);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+
+ ret = copy_to_user(data->buffer, tmp, tmp_size);
+ if (unlikely(ret)) {
+ err();
+ ret = -EFAULT;
+ goto fail;
+ }
+
+ ret = tmp_size;
+ break;
+ default:
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+fail:
+ audit_log_crypto_op(AUDIT_CRYPTO_OP_KEY_EXPORT, lst->id, -1, NULL,
+ ncr_algorithm_name(item->algorithm), item->desc,
+ item->key_id, item->key_id_size, -1, NULL, 0);
+
+ kfree(tmp);
+ _ncr_key_item_put(item);
+ return ret;
+
+}
+
+int ncr_key_import(struct ncr_lists *lst, const struct ncr_key_import *data,
+ struct nlattr *tb[])
+{
+const struct nlattr *nla;
+struct key_item_st* item = NULL;
+int ret;
+void* tmp = NULL;
+size_t tmp_size;
+
+ ret = ncr_key_item_get_write( &item, lst, data->key);
+ if (ret < 0) {
+ err();
+ return ret;
+ }
+
+ ncr_key_clear(item);
+
+ tmp = kmalloc(data->data_size, GFP_KERNEL);
+ if (tmp == NULL) {
+ err();
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ if (unlikely(copy_from_user(tmp, data->data, data->data_size))) {
+ err();
+ ret = -EFAULT;
+ goto fail;
+ }
+ tmp_size = data->data_size;
+
+ nla = tb[NCR_ATTR_KEY_TYPE];
+ if (tb == NULL) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+ item->type = nla_get_u32(nla);
+
+ item->algorithm = _ncr_nla_to_properties(tb[NCR_ATTR_ALGORITHM]);
+ if (item->algorithm == NULL) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ nla = tb[NCR_ATTR_KEY_FLAGS];
+ if (nla != NULL)
+ item->flags = nla_get_u32(nla);
+
+ nla = tb[NCR_ATTR_KEY_ID];
+ if (nla != NULL) {
+ if (nla_len(nla) > MAX_KEY_ID_SIZE) {
+ err();
+ ret = -EOVERFLOW;
+ goto fail;
+ }
+
+ item->key_id_size = nla_len(nla);
+ memcpy(item->key_id, nla_data(nla), item->key_id_size);
+ }
+
+ switch(item->type) {
+ case NCR_KEY_TYPE_SECRET:
+
+ if (tmp_size > NCR_CIPHER_MAX_KEY_LEN) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ memcpy(item->key.secret.data, tmp, tmp_size);
+ item->key.secret.size = tmp_size;
+ break;
+ case NCR_KEY_TYPE_PRIVATE:
+ case NCR_KEY_TYPE_PUBLIC:
+ ret = ncr_pk_unpack( item, tmp, tmp_size);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+ break;
+
+ default:
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ ret = 0;
+
+fail:
+ audit_log_crypto_op(AUDIT_CRYPTO_OP_KEY_IMPORT, lst->id, -1, NULL,
+ ncr_algorithm_name(item->algorithm), item->desc,
+ item->key_id, item->key_id_size, -1, NULL, 0);
+
+ _ncr_key_item_put(item);
+ kfree(tmp);
+
+ return ret;
+}
+
+static void ncr_key_clear(struct key_item_st* item)
+{
+ audit_log_crypto_op(AUDIT_CRYPTO_OP_KEY_ZEROIZE, item->context_id, -1,
+ NULL, ncr_algorithm_name(item->algorithm),
+ item->desc, item->key_id, item->key_id_size, -1,
+ NULL, 0);
+
+ /* clears any previously allocated parameters */
+ if (item->type == NCR_KEY_TYPE_PRIVATE ||
+ item->type == NCR_KEY_TYPE_PUBLIC) {
+
+ ncr_pk_clear(item);
+ }
+ memset(&item->key, 0, sizeof(item->key));
+ memset(item->key_id, 0, sizeof(item->key_id));
+ item->key_id_size = 0;
+ item->flags = 0;
+
+ return;
+}
+
+/* Generate a secret key
+ */
+int ncr_key_generate(struct ncr_lists *lst, const struct ncr_key_generate *gen,
+ struct nlattr *tb[])
+{
+const struct nlattr *nla;
+struct key_item_st* item = NULL;
+const struct algo_properties_st *algo;
+int ret;
+size_t size;
+
+ ret = ncr_key_item_get_write(&item, lst, gen->key);
+ if (ret < 0) {
+ err();
+ return ret;
+ }
+
+ ncr_key_clear(item);
+
+ /* we generate only secret keys */
+ nla = tb[NCR_ATTR_KEY_FLAGS];
+ if (nla != NULL)
+ item->flags = nla_get_u32(nla);
+
+ algo = _ncr_nla_to_properties(tb[NCR_ATTR_ALGORITHM]);
+ if (algo == NULL) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+ item->type = algo->key_type;
+ if (item->type == NCR_KEY_TYPE_SECRET) {
+ u32 key_bits;
+
+ item->algorithm = algo;
+
+ nla = tb[NCR_ATTR_SECRET_KEY_BITS];
+ if (nla == NULL) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+ key_bits = nla_get_u32(nla);
+ size = key_bits / 8;
+ if (key_bits % 8 != 0 || size > NCR_CIPHER_MAX_KEY_LEN) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ get_random_bytes(item->key.secret.data, size);
+ item->key.secret.size = size;
+
+ /* generate random key id */
+ item->key_id_size = 5;
+ get_random_bytes(item->key_id, item->key_id_size);
+ } else {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ ret = 0;
+
+fail:
+ audit_log_crypto_op(AUDIT_CRYPTO_OP_KEY_GEN, lst->id, -1, NULL,
+ ncr_algorithm_name(algo), item->desc, item->key_id,
+ item->key_id_size, -1, NULL, 0);
+
+ if (ret < 0) item->type = NCR_KEY_TYPE_INVALID;
+ _ncr_key_item_put(item);
+ return ret;
+}
+
+int ncr_key_get_info(struct ncr_lists *lst, struct ncr_out *out,
+ const struct ncr_key_get_info *info, struct nlattr *tb[])
+{
+const struct nlattr *nla;
+const u16 *attr, *attr_end;
+struct key_item_st* item = NULL;
+int ret;
+
+ ret = ncr_key_item_get_read(&item, lst, info->key);
+ if (ret < 0) {
+ err();
+ return ret;
+ }
+
+ if (item->type == NCR_KEY_TYPE_INVALID) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ nla = tb[NCR_ATTR_WANTED_ATTRS];
+ if (nla == NULL || nla_len(nla) % sizeof(u16) != 0) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+ attr = nla_data(nla);
+ attr_end = attr + nla_len(nla) / sizeof(u16);
+ while (attr < attr_end) {
+ switch (*attr) {
+ case NCR_ATTR_KEY_FLAGS:
+ ret = ncr_out_put_u32(out, *attr, item->flags);
+ break;
+ case NCR_ATTR_KEY_TYPE:
+ ret = ncr_out_put_u32(out, *attr, item->type);
+ break;
+ case NCR_ATTR_ALGORITHM:
+ ret = ncr_out_put_string(out, *attr,
+ item->algorithm->kstr);
+ break;
+ default:
+ break; /* Silently ignore */
+ }
+ if (ret != 0) {
+ err();
+ goto fail;
+ }
+ attr++;
+ }
+
+ ret = ncr_out_finish(out);
+ if (ret != 0) {
+ err();
+ goto fail;
+ }
+
+fail:
+ audit_log_crypto_op(AUDIT_CRYPTO_OP_KEY_GET_INFO, lst->id, -1, NULL,
+ ncr_algorithm_name(item->algorithm), item->desc,
+ item->key_id, item->key_id_size, -1, NULL, 0);
+
+ _ncr_key_item_put( item);
+
+ return ret;
+}
+
+int ncr_key_generate_pair(struct ncr_lists *lst,
+ const struct ncr_key_generate_pair *gen,
+ struct nlattr *tb[])
+{
+const struct nlattr *nla;
+struct key_item_st* private = NULL;
+struct key_item_st* public = NULL;
+int ret;
+
+ ret = ncr_key_item_get_write(&private, lst, gen->private_key);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+
+ ret = ncr_key_item_get_write(&public, lst, gen->public_key);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+
+ ncr_key_clear(public);
+ ncr_key_clear(private);
+
+ /* we generate only secret keys */
+ nla = tb[NCR_ATTR_KEY_FLAGS];
+ if (nla != NULL)
+ private->flags = public->flags = nla_get_u32(nla);
+
+ private->algorithm = public->algorithm
+ = _ncr_nla_to_properties(tb[NCR_ATTR_ALGORITHM]);
+ if (private->algorithm == NULL) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+ public->type = public->algorithm->key_type;
+ private->type = NCR_KEY_TYPE_PRIVATE;
+ public->flags |= (NCR_KEY_FLAG_EXPORTABLE|NCR_KEY_FLAG_WRAPPABLE);
+
+ if (public->type == NCR_KEY_TYPE_PUBLIC) {
+ ret = ncr_pk_generate(public->algorithm, tb, private, public);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+ } else {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ ret = 0;
+fail:
+ audit_log_crypto_op(AUDIT_CRYPTO_OP_KEY_GEN, lst->id, -1, NULL,
+ ncr_algorithm_name(private != NULL
+ ? private->algorithm : NULL),
+ gen->private_key,
+ private != NULL ? private->key_id : NULL,
+ private != NULL ? private->key_id_size : 0,
+ gen->public_key,
+ public != NULL ? public->key_id : NULL,
+ public != NULL ? public->key_id_size : 0);
+
+ if (public) {
+ if (ret < 0) public->type = NCR_KEY_TYPE_INVALID;
+ _ncr_key_item_put(public);
+ }
+ if (private) {
+ if (ret < 0) private->type = NCR_KEY_TYPE_INVALID;
+ _ncr_key_item_put(private);
+ }
+ return ret;
+}
+
+int ncr_key_derive(struct ncr_lists *lst, const struct ncr_key_derive *data,
+ struct nlattr *tb[])
+{
+const struct nlattr *nla;
+int ret;
+struct key_item_st* key = NULL;
+struct key_item_st* newkey = NULL;
+
+ ret = ncr_key_item_get_read(&key, lst, data->input_key);
+ if (ret < 0) {
+ err();
+ return ret;
+ }
+
+ ret = ncr_key_item_get_write(&newkey, lst, data->new_key);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+
+ ncr_key_clear(newkey);
+
+ nla = tb[NCR_ATTR_KEY_FLAGS];
+ if (nla != NULL)
+ newkey->flags = nla_get_u32(nla);
+
+ switch (key->type) {
+ case NCR_KEY_TYPE_PUBLIC:
+ case NCR_KEY_TYPE_PRIVATE:
+ ret = ncr_pk_derive(newkey, key, tb);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+ break;
+ default:
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+fail:
+ audit_log_crypto_op(AUDIT_CRYPTO_OP_KEY_DERIVE, lst->id, -1, NULL,
+ ncr_algorithm_name(key->algorithm), key->desc,
+ key->key_id, key->key_id_size, data->new_key,
+ newkey != NULL ? newkey->key_id : NULL,
+ newkey != NULL ? newkey->key_id_size : 0);
+
+ _ncr_key_item_put(key);
+ if (newkey)
+ _ncr_key_item_put(newkey);
+ return ret;
+
+}
+
--
1.7.2.1

2010-08-20 08:46:56

by Miloslav Trmac

[permalink] [raw]
Subject: [PATCH 12/19] Add DH implementation and pubkey abstraction layer

Add basic Diffie-Hellman implementation, because it is not provided by
libtomcrypt.

Finally, add an algorithm-independent pubkey interface that encapsulates
the separate pubkey algorithm implementations.
---
crypto/userspace/Makefile | 2 +-
crypto/userspace/ncr-dh.c | 282 +++++++++++++++++++
crypto/userspace/ncr-pk.c | 659 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 942 insertions(+), 1 deletions(-)
create mode 100644 crypto/userspace/ncr-dh.c
create mode 100644 crypto/userspace/ncr-pk.c

diff --git a/crypto/userspace/Makefile b/crypto/userspace/Makefile
index 0891c2b..fa4168d 100644
--- a/crypto/userspace/Makefile
+++ b/crypto/userspace/Makefile
@@ -64,7 +64,7 @@ TOMCRYPT_OBJECTS = libtomcrypt/misc/zeromem.o libtomcrypt/misc/crypt/crypt_argch
libtomcrypt/pk/asn1/der/x509/der_decode_subject_public_key_info.o

cryptodev-objs := cryptodev_main.o cryptodev_cipher.o ncr-limits.o \
- ncr-sessions.o utils.o $(TOMMATH_OBJECTS) \
+ ncr-pk.o ncr-sessions.o ncr-dh.o utils.o $(TOMMATH_OBJECTS) \
$(TOMCRYPT_OBJECTS)


diff --git a/crypto/userspace/ncr-dh.c b/crypto/userspace/ncr-dh.c
new file mode 100644
index 0000000..3a00c0b
--- /dev/null
+++ b/crypto/userspace/ncr-dh.c
@@ -0,0 +1,282 @@
+/*
+ * New driver for /dev/crypto device (aka CryptoDev)
+
+ * Copyright (c) 2010 Katholieke Universiteit Leuven
+ *
+ * Author: Nikos Mavrogiannopoulos <[email protected]>
+ *
+ * This file is part of linux cryptodev.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <linux/ioctl.h>
+#include <linux/mm.h>
+#include <linux/ncr.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/uaccess.h>
+#include <linux/scatterlist.h>
+#include <ncr-int.h>
+#include <tomcrypt.h>
+#include <ncr-dh.h>
+
+void dh_free(dh_key * key)
+{
+ mp_clear_multi(&key->p, &key->g, &key->x, NULL);
+}
+
+int dh_import_params(dh_key * key, uint8_t * p, size_t p_size, uint8_t * g,
+ size_t g_size)
+{
+ int ret;
+ int err;
+
+ if ((err =
+ mp_init_multi(&key->p, &key->g, &key->x, &key->y,
+ NULL)) != CRYPT_OK) {
+ err();
+ return -ENOMEM;
+ }
+
+ if ((err =
+ mp_read_unsigned_bin(&key->p, (unsigned char *) p,
+ p_size)) != CRYPT_OK) {
+ err();
+ ret = _ncr_tomerr(err);
+ goto fail;
+ }
+
+ if ((err =
+ mp_read_unsigned_bin(&key->g, (unsigned char *) g,
+ g_size)) != CRYPT_OK) {
+ err();
+ ret = _ncr_tomerr(err);
+ goto fail;
+ }
+
+ return 0;
+ fail:
+ mp_clear_multi(&key->p, &key->g, &key->x, &key->y, NULL);
+
+ return ret;
+}
+
+int dh_generate_key(dh_key * key)
+{
+ void *buf;
+ int size;
+ int err, ret;
+
+ size = mp_unsigned_bin_size(&key->p);
+ if (size == 0) {
+ err();
+ return -EINVAL;
+ }
+
+ buf = kmalloc(size, GFP_KERNEL);
+ if (buf == NULL) {
+ err();
+ return -ENOMEM;
+ }
+
+ get_random_bytes(buf, size);
+
+ if ((err = mp_read_unsigned_bin(&key->x, buf, size)) != CRYPT_OK) {
+ err();
+ ret = _ncr_tomerr(err);
+ goto fail;
+ }
+
+ err = mp_mod(&key->x, &key->p, &key->x);
+ if (err != CRYPT_OK) {
+ err();
+ ret = _ncr_tomerr(err);
+ goto fail;
+ }
+
+ key->type = PK_PRIVATE;
+
+ ret = 0;
+ fail:
+ kfree(buf);
+
+ return ret;
+
+}
+
+int dh_generate_public(dh_key * public, dh_key * private)
+{
+ int err, ret;
+
+ err =
+ mp_exptmod(&private->g, &private->x, &private->p, &public->y);
+ if (err != CRYPT_OK) {
+ err();
+ ret = _ncr_tomerr(err);
+ goto fail;
+ }
+
+ public->type = PK_PUBLIC;
+
+ ret = 0;
+ fail:
+
+ return ret;
+}
+
+int dh_export(uint8_t * out, unsigned long * outlen, int type, dh_key * key)
+{
+ unsigned long zero = 0;
+ int err;
+
+ if (out == NULL || outlen == NULL || key == NULL) {
+ err();
+ return -EINVAL;
+ }
+
+ /* can we store the static header? */
+ if (type == PK_PRIVATE && key->type != PK_PRIVATE) {
+ return -EINVAL;
+ }
+
+ if (type != PK_PUBLIC && type != PK_PRIVATE) {
+ return -EINVAL;
+ }
+
+ /* This encoding is different from the one in original
+ * libtomcrypt. It uses a compatible encoding with gnutls
+ * and openssl
+ */
+ if (type == PK_PRIVATE) {
+ err = der_encode_sequence_multi(out, outlen,
+ LTC_ASN1_SHORT_INTEGER, 1UL, &zero,
+ LTC_ASN1_INTEGER, 1UL, &key->p,
+ LTC_ASN1_INTEGER, 1UL, &key->g,
+ LTC_ASN1_INTEGER, 1UL, &key->x,
+ LTC_ASN1_EOL, 0UL, NULL);
+ } else {
+ err = mp_unsigned_bin_size(&key->y);
+ if (err > *outlen) {
+ err();
+ return -EOVERFLOW;
+ }
+
+ *outlen = err;
+
+ err = mp_to_unsigned_bin(&key->y, out);
+ }
+
+ if (err != CRYPT_OK) {
+ err();
+ return _ncr_tomerr(err);
+ }
+
+ return 0;
+}
+
+int dh_import(const uint8_t * in, size_t inlen, dh_key * key)
+{
+ int err;
+ unsigned long zero = 0;
+
+ if (in == NULL || key == NULL) {
+ err();
+ return -EINVAL;
+ }
+
+ /* init key */
+ if (mp_init_multi
+ (&key->p, &key->g, &key->x, &key->y, NULL) != CRYPT_OK) {
+ return -ENOMEM;
+ }
+
+ /* get key type */
+ if ((err = der_decode_sequence_multi(in, inlen,
+ LTC_ASN1_SHORT_INTEGER, 1UL, &zero,
+ LTC_ASN1_INTEGER, 1UL, &key->p,
+ LTC_ASN1_INTEGER, 1UL, &key->g,
+ LTC_ASN1_INTEGER, 1UL, &key->x,
+ LTC_ASN1_EOL, 0UL, NULL)) == CRYPT_OK) {
+ key->type = PK_PRIVATE;
+ } else { /* public */
+ err = mp_read_unsigned_bin(&key->y, in, inlen);
+ key->type = PK_PUBLIC;
+ }
+
+ if (err != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ return 0;
+
+ LBL_ERR:
+ mp_clear_multi(&key->p, &key->g, &key->x, &key->y, NULL);
+ return _ncr_tomerr(err);
+}
+
+int dh_derive_gxy(struct key_item_st* newkey, dh_key * key,
+ void* pk, size_t pk_size)
+{
+int ret, err;
+mp_int y, gxy;
+ /* newkey will be a secret key with value of g^{xy}
+ */
+
+ if (mp_init_multi(&y, &gxy, NULL) != CRYPT_OK) {
+ err();
+ return -ENOMEM;
+ }
+
+ if (key->type != PK_PRIVATE) {
+ err();
+ return -EINVAL;
+ }
+
+ if ((err=mp_read_unsigned_bin(&y, pk, pk_size)) != CRYPT_OK) {
+ err();
+ ret = _ncr_tomerr(err);
+ goto fail;
+ }
+
+ if ((err=mp_exptmod(&y, &key->x, &key->p, &gxy))!= CRYPT_OK) {
+ err();
+ ret = _ncr_tomerr(err);
+ goto fail;
+ }
+
+ err = mp_unsigned_bin_size(&gxy);
+ if (err > NCR_CIPHER_MAX_KEY_LEN) {
+ err();
+ ret = -EOVERFLOW;
+ goto fail;
+ }
+ newkey->key.secret.size = err;
+
+ err = mp_to_unsigned_bin(&gxy, newkey->key.secret.data);
+ if (err != CRYPT_OK) {
+ err();
+ ret = _ncr_tomerr(err);
+ goto fail;
+ }
+
+ newkey->type = NCR_KEY_TYPE_SECRET;
+
+ ret = 0;
+fail:
+ mp_clear_multi(&y, &gxy, NULL);
+
+ return ret;
+}
diff --git a/crypto/userspace/ncr-pk.c b/crypto/userspace/ncr-pk.c
new file mode 100644
index 0000000..2ae3f27
--- /dev/null
+++ b/crypto/userspace/ncr-pk.c
@@ -0,0 +1,659 @@
+/*
+ * New driver for /dev/crypto device (aka CryptoDev)
+
+ * Copyright (c) 2010 Katholieke Universiteit Leuven
+ *
+ * Author: Nikos Mavrogiannopoulos <[email protected]>
+ *
+ * This file is part of linux cryptodev.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <linux/ioctl.h>
+#include <linux/mm.h>
+#include <linux/ncr.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/uaccess.h>
+#include <linux/scatterlist.h>
+#include <net/netlink.h>
+#include "ncr-int.h"
+#include <tomcrypt.h>
+
+int _ncr_tomerr(int err)
+{
+ switch (err) {
+ case CRYPT_BUFFER_OVERFLOW:
+ return -ERANGE;
+ case CRYPT_MEM:
+ return -ENOMEM;
+ default:
+ return -EINVAL;
+ }
+}
+
+void ncr_pk_clear(struct key_item_st* key)
+{
+ if (key->algorithm == NULL)
+ return;
+ switch(key->algorithm->algo) {
+ case NCR_ALG_RSA:
+ rsa_free(&key->key.pk.rsa);
+ break;
+ case NCR_ALG_DSA:
+ dsa_free(&key->key.pk.dsa);
+ break;
+ case NCR_ALG_DH:
+ dh_free(&key->key.pk.dh);
+ break;
+ default:
+ return;
+ }
+}
+
+static int ncr_pk_make_public_and_id( struct key_item_st * private, struct key_item_st * public)
+{
+ uint8_t * tmp;
+ unsigned long max_size;
+ int ret, cret;
+ unsigned long key_id_size;
+
+ max_size = KEY_DATA_MAX_SIZE;
+ tmp = kmalloc(max_size, GFP_KERNEL);
+ if (tmp == NULL) {
+ err();
+ return -ENOMEM;
+ }
+
+ switch(private->algorithm->algo) {
+ case NCR_ALG_RSA:
+ cret = rsa_export(tmp, &max_size, PK_PUBLIC, &private->key.pk.rsa);
+ if (cret != CRYPT_OK) {
+ err();
+ ret = _ncr_tomerr(cret);
+ goto fail;
+ }
+
+ cret = rsa_import(tmp, max_size, &public->key.pk.rsa);
+ if (cret != CRYPT_OK) {
+ err();
+ ret = _ncr_tomerr(cret);
+ goto fail;
+ }
+ break;
+ case NCR_ALG_DSA:
+ cret = dsa_export(tmp, &max_size, PK_PUBLIC, &private->key.pk.dsa);
+ if (cret != CRYPT_OK) {
+ err();
+ ret = _ncr_tomerr(cret);
+ goto fail;
+ }
+
+ cret = dsa_import(tmp, max_size, &public->key.pk.dsa);
+ if (cret != CRYPT_OK) {
+ err();
+ ret = _ncr_tomerr(cret);
+ goto fail;
+ }
+ break;
+ case NCR_ALG_DH:
+ ret = dh_generate_public(&public->key.pk.dh, &private->key.pk.dh);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+ break;
+ default:
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ key_id_size = MAX_KEY_ID_SIZE;
+ cret = hash_memory(_ncr_algo_to_properties("sha1"), tmp, max_size,
+ private->key_id, &key_id_size);
+ if (cret != CRYPT_OK) {
+ err();
+ ret = _ncr_tomerr(cret);
+ goto fail;
+ }
+ private->key_id_size = public->key_id_size = key_id_size;
+ memcpy(public->key_id, private->key_id, key_id_size);
+
+ ret = 0;
+fail:
+ kfree(tmp);
+
+ return ret;
+}
+
+int ncr_pk_pack( const struct key_item_st * key, uint8_t * packed, uint32_t * packed_size)
+{
+ unsigned long max_size = *packed_size;
+ int cret, ret;
+
+ if (packed == NULL || packed_size == NULL) {
+ err();
+ return -EINVAL;
+ }
+
+ switch(key->algorithm->algo) {
+ case NCR_ALG_RSA:
+ cret = rsa_export(packed, &max_size, key->key.pk.rsa.type, (void*)&key->key.pk.rsa);
+ if (cret != CRYPT_OK) {
+ *packed_size = max_size;
+ err();
+ return _ncr_tomerr(cret);
+ }
+ break;
+ case NCR_ALG_DSA:
+ cret = dsa_export(packed, &max_size, key->key.pk.dsa.type, (void*)&key->key.pk.dsa);
+ if (cret != CRYPT_OK) {
+ *packed_size = max_size;
+ err();
+ return _ncr_tomerr(cret);
+ }
+ break;
+ case NCR_ALG_DH:
+ ret = dh_export(packed, &max_size, key->key.pk.dsa.type, (void*)&key->key.pk.dsa);
+ if (ret < 0) {
+ err();
+ return ret;
+ }
+ break;
+ default:
+ err();
+ return -EINVAL;
+ }
+
+ *packed_size = max_size;
+
+ return 0;
+}
+
+int ncr_pk_unpack( struct key_item_st * key, const void * packed, size_t packed_size)
+{
+ int cret, ret;
+
+ if (key == NULL || packed == NULL) {
+ err();
+ return -EINVAL;
+ }
+
+ switch(key->algorithm->algo) {
+ case NCR_ALG_RSA:
+ cret = rsa_import(packed, packed_size, (void*)&key->key.pk.rsa);
+ if (cret != CRYPT_OK) {
+ err();
+ return _ncr_tomerr(cret);
+ }
+ break;
+ case NCR_ALG_DSA:
+ cret = dsa_import(packed, packed_size, (void*)&key->key.pk.dsa);
+ if (cret != CRYPT_OK) {
+ err();
+ return _ncr_tomerr(cret);
+ }
+ break;
+ case NCR_ALG_DH:
+ ret = dh_import(packed, packed_size, (void*)&key->key.pk.dh);
+ if (ret < 0) {
+ err();
+ return ret;
+ }
+ break;
+ default:
+ err();
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int binary_to_ulong(unsigned long *dest, const struct nlattr *nla)
+{
+ unsigned long value;
+ const uint8_t *start, *end, *p;
+
+ value = 0;
+ start = nla_data(nla);
+ end = start + nla_len(nla);
+ for (p = start; p < end; p++) {
+ if (value > (ULONG_MAX - *p) / 256)
+ return -EOVERFLOW;
+ value = value * 256 + *p;
+ }
+ *dest = value;
+ return 0;
+}
+
+int ncr_pk_generate(const struct algo_properties_st *algo, struct nlattr *tb[],
+ struct key_item_st* private, struct key_item_st* public)
+{
+ const struct nlattr *nla;
+ unsigned long e;
+ int cret, ret;
+
+ private->algorithm = public->algorithm = algo;
+
+ ret = 0;
+ switch(algo->algo) {
+ case NCR_ALG_RSA:
+ nla = tb[NCR_ATTR_RSA_E];
+ if (nla != NULL) {
+ ret = binary_to_ulong(&e, nla);
+ if (ret != 0)
+ break;
+ } else
+ e = 65537;
+
+ nla = tb[NCR_ATTR_RSA_MODULUS_BITS];
+ if (nla == NULL) {
+ ret = -EINVAL;
+ break;
+ }
+ cret = rsa_make_key(nla_get_u32(nla) / 8, e,
+ &private->key.pk.rsa);
+ if (cret != CRYPT_OK) {
+ err();
+ return _ncr_tomerr(cret);
+ }
+ break;
+ case NCR_ALG_DSA: {
+ u32 q_bits, p_bits;
+
+ nla = tb[NCR_ATTR_DSA_Q_BITS];
+ if (nla != NULL)
+ q_bits = nla_get_u32(nla);
+ else
+ q_bits = 160;
+ nla = tb[NCR_ATTR_DSA_P_BITS];
+ if (nla != NULL)
+ p_bits = nla_get_u32(nla);
+ else
+ p_bits = 1024;
+ cret = dsa_make_key(q_bits / 8, p_bits / 8,
+ &private->key.pk.dsa);
+ if (cret != CRYPT_OK) {
+ err();
+ return _ncr_tomerr(cret);
+ }
+ break;
+ }
+ case NCR_ALG_DH: {
+ const struct nlattr *p, *g;
+
+ p = tb[NCR_ATTR_DH_PRIME];
+ g = tb[NCR_ATTR_DH_BASE];
+ if (p == NULL || g == NULL) {
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ ret = dh_import_params(&private->key.pk.dh, nla_data(p),
+ nla_len(p), nla_data(g),
+ nla_len(g));
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+
+ ret = dh_generate_key(&private->key.pk.dh);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+ break;
+ }
+ default:
+ err();
+ return -EINVAL;
+ }
+
+fail:
+ if (ret < 0) {
+ err();
+ return ret;
+ }
+
+ ret = ncr_pk_make_public_and_id(private, public);
+ if (ret < 0) {
+ err();
+ return ret;
+ }
+
+ return 0;
+}
+
+/* Encryption/Decryption
+ */
+
+void ncr_pk_cipher_deinit(struct ncr_pk_ctx* ctx)
+{
+ if (ctx->init) {
+ ctx->init = 0;
+ ctx->key = NULL;
+ }
+}
+
+int ncr_pk_cipher_init(const struct algo_properties_st *algo,
+ struct ncr_pk_ctx* ctx, struct nlattr *tb[],
+ struct key_item_st *key,
+ const struct algo_properties_st *sign_hash)
+{
+ const struct nlattr *nla;
+
+ memset(ctx, 0, sizeof(*ctx));
+
+ if (key->algorithm != algo) {
+ err();
+ return -EINVAL;
+ }
+
+ ctx->algorithm = algo;
+ ctx->key = key;
+ ctx->sign_hash = sign_hash;
+ ctx->salt_len = 0;
+
+ switch(algo->algo) {
+ case NCR_ALG_RSA:
+ nla = tb[NCR_ATTR_RSA_ENCODING_METHOD];
+ if (nla == NULL) {
+ err();
+ return -EINVAL;
+ }
+ switch (nla_get_u32(nla)) {
+ case RSA_PKCS1_V1_5:
+ ctx->type = LTC_LTC_PKCS_1_V1_5;
+ break;
+ case RSA_PKCS1_OAEP:
+ ctx->type = LTC_LTC_PKCS_1_OAEP;
+ nla = tb[NCR_ATTR_RSA_OAEP_HASH_ALGORITHM];
+ ctx->oaep_hash = _ncr_nla_to_properties(nla);
+ if (ctx->oaep_hash == NULL) {
+ err();
+ return -EINVAL;
+ }
+ break;
+ case RSA_PKCS1_PSS:
+ ctx->type = LTC_LTC_PKCS_1_PSS;
+ nla = tb[NCR_ATTR_RSA_PSS_SALT_LENGTH];
+ if (nla != NULL)
+ ctx->salt_len = nla_get_u32(nla);
+ break;
+ default:
+ err();
+ return -EINVAL;
+ }
+ break;
+ case NCR_ALG_DSA:
+ break;
+ default:
+ err();
+ return -EINVAL;
+ }
+
+ ctx->init = 1;
+
+ return 0;
+}
+
+int ncr_pk_cipher_encrypt(const struct ncr_pk_ctx* ctx,
+ const struct scatterlist* isg, unsigned int isg_cnt, size_t isg_size,
+ struct scatterlist *osg, unsigned int osg_cnt, size_t* osg_size)
+{
+int cret, ret;
+unsigned long osize = *osg_size;
+uint8_t* tmp;
+void * input, *output;
+
+ tmp = kmalloc(isg_size + *osg_size, GFP_KERNEL);
+ if (tmp == NULL) {
+ err();
+ return -ENOMEM;
+ }
+
+ ret = sg_copy_to_buffer((struct scatterlist*)isg, isg_cnt, tmp, isg_size);
+ if (ret != isg_size) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ input = tmp;
+ output = &tmp[isg_size];
+
+
+ switch(ctx->algorithm->algo) {
+ case NCR_ALG_RSA:
+ cret = rsa_encrypt_key_ex( input, isg_size, output, &osize,
+ NULL, 0, ctx->oaep_hash, ctx->type, &ctx->key->key.pk.rsa);
+
+ if (cret != CRYPT_OK) {
+ err();
+ ret = _ncr_tomerr(cret);
+ goto fail;
+ }
+ *osg_size = osize;
+
+ break;
+ case NCR_ALG_DSA:
+ ret = -EINVAL;
+ goto fail;
+ default:
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ ret = sg_copy_from_buffer(osg, osg_cnt, output, *osg_size);
+ if (ret != *osg_size) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ ret = 0;
+
+fail:
+ kfree(tmp);
+ return ret;
+}
+
+int ncr_pk_cipher_decrypt(const struct ncr_pk_ctx* ctx,
+ const struct scatterlist* isg, unsigned int isg_cnt, size_t isg_size,
+ struct scatterlist *osg, unsigned int osg_cnt, size_t* osg_size)
+{
+int cret, ret;
+int stat;
+unsigned long osize = *osg_size;
+uint8_t* tmp;
+void * input, *output;
+
+ tmp = kmalloc(isg_size + *osg_size, GFP_KERNEL);
+ if (tmp == NULL) {
+ err();
+ return -ENOMEM;
+ }
+
+ input = tmp;
+ output = &tmp[isg_size];
+
+ ret = sg_copy_to_buffer((struct scatterlist*)isg, isg_cnt, input, isg_size);
+ if (ret != isg_size) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ switch(ctx->algorithm->algo) {
+ case NCR_ALG_RSA:
+ cret = rsa_decrypt_key_ex( input, isg_size, output, &osize,
+ NULL, 0, ctx->oaep_hash, ctx->type, &stat, &ctx->key->key.pk.rsa);
+
+ if (cret != CRYPT_OK) {
+ err();
+ ret = _ncr_tomerr(cret);
+ goto fail;
+ }
+
+ if (stat==0) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+ *osg_size = osize;
+ break;
+ case NCR_ALG_DSA:
+ ret = -EINVAL;
+ goto fail;
+ default:
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ ret = sg_copy_from_buffer(osg, osg_cnt, output, *osg_size);
+ if (ret != *osg_size) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ ret = 0;
+fail:
+ kfree(tmp);
+
+ return ret;
+}
+
+int ncr_pk_cipher_sign(const struct ncr_pk_ctx *ctx, const void *hash,
+ size_t hash_size, void *sig, size_t *sig_size)
+{
+ int cret;
+ unsigned long osize = *sig_size;
+
+ switch(ctx->algorithm->algo) {
+ case NCR_ALG_RSA:
+ if (ctx->sign_hash == NULL) {
+ err();
+ return -EINVAL;
+ }
+ cret = rsa_sign_hash_ex(hash, hash_size, sig, &osize,
+ ctx->type, ctx->sign_hash, ctx->salt_len, &ctx->key->key.pk.rsa);
+ if (cret != CRYPT_OK) {
+ err();
+ return _ncr_tomerr(cret);
+ }
+ *sig_size = osize;
+ break;
+ case NCR_ALG_DSA:
+ cret = dsa_sign_hash(hash, hash_size, sig, &osize,
+ &ctx->key->key.pk.dsa);
+
+ if (cret != CRYPT_OK) {
+ err();
+ return _ncr_tomerr(cret);
+ }
+ *sig_size = osize;
+ break;
+ default:
+ err();
+ return -EINVAL;
+ }
+ return 0;
+}
+
+int ncr_pk_cipher_verify(const struct ncr_pk_ctx* ctx, const void *sig,
+ size_t sig_size, const void *hash, size_t hash_size)
+{
+ int cret, ret, stat;
+
+ switch(ctx->algorithm->algo) {
+ case NCR_ALG_RSA:
+ if (ctx->sign_hash == NULL) {
+ err();
+ return -EINVAL;
+ }
+ cret = rsa_verify_hash_ex(sig, sig_size, hash,
+ hash_size, ctx->type,
+ ctx->sign_hash, ctx->salt_len,
+ &stat, &ctx->key->key.pk.rsa);
+ if (cret != CRYPT_OK) {
+ err();
+ ret = _ncr_tomerr(cret);
+ goto fail;
+ }
+
+ ret = (stat == 1);
+ break;
+ case NCR_ALG_DSA:
+ cret = dsa_verify_hash(sig, sig_size, hash, hash_size,
+ &stat, &ctx->key->key.pk.dsa);
+ if (cret != CRYPT_OK) {
+ err();
+ ret = _ncr_tomerr(cret);
+ goto fail;
+ }
+
+ ret = (stat == 1);
+ break;
+ default:
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+fail:
+ return ret;
+}
+
+int ncr_pk_derive(struct key_item_st* newkey, struct key_item_st* oldkey,
+ struct nlattr *tb[])
+{
+const struct nlattr *nla;
+int ret;
+
+ nla = tb[NCR_ATTR_DERIVATION_ALGORITHM];
+ if (nla == NULL) {
+ err();
+ return -EINVAL;
+ }
+ if (nla_strcmp(nla, NCR_DERIVE_DH) == 0) {
+ if (oldkey->type != NCR_KEY_TYPE_PRIVATE &&
+ oldkey->algorithm->algo != NCR_ALG_DH) {
+ err();
+ return -EINVAL;
+ }
+
+ nla = tb[NCR_ATTR_DH_PUBLIC];
+ if (nla == NULL) {
+ err();
+ return -EINVAL;
+ }
+ ret = dh_derive_gxy(newkey, &oldkey->key.pk.dh, nla_data(nla),
+ nla_len(nla));
+ if (ret < 0) {
+ err();
+ return ret;
+ }
+ } else {
+ err();
+ return -EINVAL;
+ }
+
+ return 0;
+}
--
1.7.2.1

2010-08-20 08:45:54

by Miloslav Trmac

[permalink] [raw]
Subject: [PATCH 10/19] Add libtommath implementation

No use postponing it any more I'm afraid.

(Reviewing this in detail is probably premature, we are considering
replacing the implementation by something based on libgcrypt, which is
more actively maintained and has been probably more thorouhgly examined
for vulnerabilities.)
---
crypto/userspace/Makefile | 38 ++-
.../libtomcrypt/hashes/crypt_hash_is_valid.c | 30 ++
crypto/userspace/libtomcrypt/hashes/hash_get_oid.c | 78 ++++
crypto/userspace/libtomcrypt/hashes/hash_memory.c | 66 ++++
.../libtomcrypt/hashes/hash_memory_multi.c | 84 +++++
.../userspace/libtomcrypt/headers/tomcrypt_prng.h | 80 ++++
crypto/userspace/libtomcrypt/math/rand_prime.c | 80 ++++
.../libtomcrypt/misc/crypt/crypt_argchk.c | 28 ++
crypto/userspace/libtomcrypt/misc/pk_get_oid.c | 40 ++
crypto/userspace/libtomcrypt/misc/qsort.c | 247 ++++++++++++
crypto/userspace/libtomcrypt/misc/zeromem.c | 34 ++
.../pk/asn1/der/bit/der_decode_bit_string.c | 106 ++++++
.../pk/asn1/der/bit/der_encode_bit_string.c | 92 +++++
.../pk/asn1/der/bit/der_length_bit_string.c | 54 +++
.../pk/asn1/der/boolean/der_decode_boolean.c | 47 +++
.../pk/asn1/der/boolean/der_encode_boolean.c | 51 +++
.../pk/asn1/der/boolean/der_length_boolean.c | 35 ++
.../pk/asn1/der/choice/der_decode_choice.c | 182 +++++++++
.../pk/asn1/der/ia5/der_decode_ia5_string.c | 96 +++++
.../pk/asn1/der/ia5/der_encode_ia5_string.c | 85 +++++
.../pk/asn1/der/ia5/der_length_ia5_string.c | 194 ++++++++++
.../pk/asn1/der/integer/der_decode_integer.c | 110 ++++++
.../pk/asn1/der/integer/der_encode_integer.c | 130 +++++++
.../pk/asn1/der/integer/der_length_integer.c | 82 ++++
.../der_decode_object_identifier.c | 99 +++++
.../der_encode_object_identifier.c | 111 ++++++
.../der_length_object_identifier.c | 89 +++++
.../pk/asn1/der/octet/der_decode_octet_string.c | 91 +++++
.../pk/asn1/der/octet/der_encode_octet_string.c | 86 +++++
.../pk/asn1/der/octet/der_length_octet_string.c | 53 +++
.../printable_string/der_decode_printable_string.c | 96 +++++
.../printable_string/der_encode_printable_string.c | 85 +++++
.../printable_string/der_length_printable_string.c | 166 ++++++++
.../pk/asn1/der/sequence/der_decode_sequence_ex.c | 287 ++++++++++++++
.../asn1/der/sequence/der_decode_sequence_flexi.c | 394 ++++++++++++++++++++
.../asn1/der/sequence/der_decode_sequence_multi.c | 140 +++++++
.../pk/asn1/der/sequence/der_encode_sequence_ex.c | 335 +++++++++++++++++
.../asn1/der/sequence/der_encode_sequence_multi.c | 139 +++++++
.../pk/asn1/der/sequence/der_length_sequence.c | 169 +++++++++
.../pk/asn1/der/sequence/der_sequence_free.c | 66 ++++
.../libtomcrypt/pk/asn1/der/set/der_encode_set.c | 104 +++++
.../libtomcrypt/pk/asn1/der/set/der_encode_setof.c | 163 ++++++++
.../der/short_integer/der_decode_short_integer.c | 68 ++++
.../der/short_integer/der_encode_short_integer.c | 97 +++++
.../der/short_integer/der_length_short_integer.c | 70 ++++
.../pk/asn1/der/utctime/der_decode_utctime.c | 127 +++++++
.../pk/asn1/der/utctime/der_encode_utctime.c | 83 ++++
.../pk/asn1/der/utctime/der_length_utctime.c | 46 +++
.../pk/asn1/der/utf8/der_decode_utf8_string.c | 111 ++++++
.../pk/asn1/der/utf8/der_encode_utf8_string.c | 105 ++++++
.../pk/asn1/der/utf8/der_length_utf8_string.c | 83 ++++
.../der/x509/der_decode_subject_public_key_info.c | 112 ++++++
.../der/x509/der_encode_subject_public_key_info.c | 83 ++++
crypto/userspace/libtomcrypt/pk/dsa/dsa_export.c | 99 +++++
crypto/userspace/libtomcrypt/pk/dsa/dsa_free.c | 34 ++
crypto/userspace/libtomcrypt/pk/dsa/dsa_import.c | 101 +++++
crypto/userspace/libtomcrypt/pk/dsa/dsa_make_key.c | 125 ++++++
.../userspace/libtomcrypt/pk/dsa/dsa_sign_hash.c | 147 ++++++++
.../userspace/libtomcrypt/pk/dsa/dsa_verify_hash.c | 126 +++++++
.../userspace/libtomcrypt/pk/dsa/dsa_verify_key.c | 100 +++++
.../userspace/libtomcrypt/pk/pkcs1/pkcs_1_i2osp.c | 51 +++
.../userspace/libtomcrypt/pk/pkcs1/pkcs_1_mgf1.c | 91 +++++
.../libtomcrypt/pk/pkcs1/pkcs_1_oaep_decode.c | 192 ++++++++++
.../libtomcrypt/pk/pkcs1/pkcs_1_oaep_encode.c | 164 ++++++++
.../userspace/libtomcrypt/pk/pkcs1/pkcs_1_os2ip.c | 36 ++
.../libtomcrypt/pk/pkcs1/pkcs_1_pss_decode.c | 168 +++++++++
.../libtomcrypt/pk/pkcs1/pkcs_1_pss_encode.c | 157 ++++++++
.../libtomcrypt/pk/pkcs1/pkcs_1_v1_5_decode.c | 110 ++++++
.../libtomcrypt/pk/pkcs1/pkcs_1_v1_5_encode.c | 95 +++++
.../userspace/libtomcrypt/pk/rsa/rsa_decrypt_key.c | 107 ++++++
.../userspace/libtomcrypt/pk/rsa/rsa_encrypt_key.c | 96 +++++
crypto/userspace/libtomcrypt/pk/rsa/rsa_export.c | 87 +++++
crypto/userspace/libtomcrypt/pk/rsa/rsa_exptmod.c | 147 ++++++++
crypto/userspace/libtomcrypt/pk/rsa/rsa_free.c | 34 ++
crypto/userspace/libtomcrypt/pk/rsa/rsa_import.c | 128 +++++++
crypto/userspace/libtomcrypt/pk/rsa/rsa_make_key.c | 105 ++++++
.../userspace/libtomcrypt/pk/rsa/rsa_sign_hash.c | 130 +++++++
.../userspace/libtomcrypt/pk/rsa/rsa_verify_hash.c | 170 +++++++++
78 files changed, 8526 insertions(+), 1 deletions(-)
create mode 100644 crypto/userspace/libtomcrypt/hashes/crypt_hash_is_valid.c
create mode 100644 crypto/userspace/libtomcrypt/hashes/hash_get_oid.c
create mode 100644 crypto/userspace/libtomcrypt/hashes/hash_memory.c
create mode 100644 crypto/userspace/libtomcrypt/hashes/hash_memory_multi.c
create mode 100644 crypto/userspace/libtomcrypt/headers/tomcrypt_prng.h
create mode 100644 crypto/userspace/libtomcrypt/math/rand_prime.c
create mode 100644 crypto/userspace/libtomcrypt/misc/crypt/crypt_argchk.c
create mode 100644 crypto/userspace/libtomcrypt/misc/pk_get_oid.c
create mode 100644 crypto/userspace/libtomcrypt/misc/qsort.c
create mode 100644 crypto/userspace/libtomcrypt/misc/zeromem.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/bit/der_decode_bit_string.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/bit/der_encode_bit_string.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/bit/der_length_bit_string.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/boolean/der_decode_boolean.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/boolean/der_encode_boolean.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/boolean/der_length_boolean.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/choice/der_decode_choice.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/ia5/der_decode_ia5_string.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/ia5/der_encode_ia5_string.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/ia5/der_length_ia5_string.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/integer/der_decode_integer.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/integer/der_encode_integer.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/integer/der_length_integer.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/object_identifier/der_decode_object_identifier.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/object_identifier/der_encode_object_identifier.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/object_identifier/der_length_object_identifier.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/octet/der_decode_octet_string.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/octet/der_encode_octet_string.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/octet/der_length_octet_string.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/printable_string/der_decode_printable_string.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/printable_string/der_encode_printable_string.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/printable_string/der_length_printable_string.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_ex.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_flexi.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_multi.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_encode_sequence_ex.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_encode_sequence_multi.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_length_sequence.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_sequence_free.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/set/der_encode_set.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/set/der_encode_setof.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/short_integer/der_decode_short_integer.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/short_integer/der_encode_short_integer.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/short_integer/der_length_short_integer.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/utctime/der_decode_utctime.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/utctime/der_encode_utctime.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/utctime/der_length_utctime.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/utf8/der_decode_utf8_string.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/utf8/der_encode_utf8_string.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/utf8/der_length_utf8_string.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/x509/der_decode_subject_public_key_info.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/x509/der_encode_subject_public_key_info.c
create mode 100644 crypto/userspace/libtomcrypt/pk/dsa/dsa_export.c
create mode 100644 crypto/userspace/libtomcrypt/pk/dsa/dsa_free.c
create mode 100644 crypto/userspace/libtomcrypt/pk/dsa/dsa_import.c
create mode 100644 crypto/userspace/libtomcrypt/pk/dsa/dsa_make_key.c
create mode 100644 crypto/userspace/libtomcrypt/pk/dsa/dsa_sign_hash.c
create mode 100644 crypto/userspace/libtomcrypt/pk/dsa/dsa_verify_hash.c
create mode 100644 crypto/userspace/libtomcrypt/pk/dsa/dsa_verify_key.c
create mode 100644 crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_i2osp.c
create mode 100644 crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_mgf1.c
create mode 100644 crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_oaep_decode.c
create mode 100644 crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_oaep_encode.c
create mode 100644 crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_os2ip.c
create mode 100644 crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_pss_decode.c
create mode 100644 crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_pss_encode.c
create mode 100644 crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_v1_5_decode.c
create mode 100644 crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_v1_5_encode.c
create mode 100644 crypto/userspace/libtomcrypt/pk/rsa/rsa_decrypt_key.c
create mode 100644 crypto/userspace/libtomcrypt/pk/rsa/rsa_encrypt_key.c
create mode 100644 crypto/userspace/libtomcrypt/pk/rsa/rsa_export.c
create mode 100644 crypto/userspace/libtomcrypt/pk/rsa/rsa_exptmod.c
create mode 100644 crypto/userspace/libtomcrypt/pk/rsa/rsa_free.c
create mode 100644 crypto/userspace/libtomcrypt/pk/rsa/rsa_import.c
create mode 100644 crypto/userspace/libtomcrypt/pk/rsa/rsa_make_key.c
create mode 100644 crypto/userspace/libtomcrypt/pk/rsa/rsa_sign_hash.c
create mode 100644 crypto/userspace/libtomcrypt/pk/rsa/rsa_verify_hash.c

diff --git a/crypto/userspace/Makefile b/crypto/userspace/Makefile
index 60a9b31..81e4122 100644
--- a/crypto/userspace/Makefile
+++ b/crypto/userspace/Makefile
@@ -28,8 +28,44 @@ TOMMATH_OBJECTS = libtommath/bncore.o libtommath/bn_mp_init.o libtommath/bn_mp_c
libtommath/bn_mp_init_set_int.o libtommath/bn_mp_invmod_slow.o libtommath/bn_mp_prime_rabin_miller_trials.o \
libtommath/bn_mp_to_signed_bin_n.o libtommath/bn_mp_to_unsigned_bin_n.o

+TOMCRYPT_OBJECTS = libtomcrypt/misc/zeromem.o libtomcrypt/misc/crypt/crypt_argchk.o \
+ libtomcrypt/math/rand_prime.o libtomcrypt/misc/qsort.o libtomcrypt/hashes/hash_get_oid.o \
+ libtomcrypt/hashes/crypt_hash_is_valid.o libtomcrypt/hashes/hash_memory.o libtomcrypt/hashes/hash_memory_multi.o \
+ libtomcrypt/pk/dsa/dsa_make_key.o libtomcrypt/pk/dsa/dsa_export.o libtomcrypt/pk/dsa/dsa_import.o \
+ libtomcrypt/pk/dsa/dsa_free.o libtomcrypt/pk/dsa/dsa_sign_hash.o libtomcrypt/pk/dsa/dsa_verify_hash.o \
+ libtomcrypt/pk/dsa/dsa_verify_key.o \
+ libtomcrypt/pk/asn1/der/bit/der_decode_bit_string.o libtomcrypt/pk/asn1/der/bit/der_encode_bit_string.o \
+ libtomcrypt/pk/asn1/der/bit/der_length_bit_string.o libtomcrypt/pk/asn1/der/boolean/der_decode_boolean.o \
+ libtomcrypt/pk/asn1/der/boolean/der_encode_boolean.o libtomcrypt/pk/asn1/der/boolean/der_length_boolean.o \
+ libtomcrypt/pk/asn1/der/choice/der_decode_choice.o libtomcrypt/pk/asn1/der/ia5/der_decode_ia5_string.o \
+ libtomcrypt/pk/asn1/der/ia5/der_encode_ia5_string.o libtomcrypt/pk/asn1/der/ia5/der_length_ia5_string.o \
+ libtomcrypt/pk/asn1/der/integer/der_decode_integer.o libtomcrypt/pk/asn1/der/integer/der_encode_integer.o \
+ libtomcrypt/pk/asn1/der/integer/der_length_integer.o libtomcrypt/pk/asn1/der/object_identifier/der_decode_object_identifier.o \
+ libtomcrypt/pk/asn1/der/object_identifier/der_encode_object_identifier.o libtomcrypt/pk/asn1/der/object_identifier/der_length_object_identifier.o \
+ libtomcrypt/pk/asn1/der/octet/der_decode_octet_string.o libtomcrypt/pk/asn1/der/octet/der_encode_octet_string.o \
+ libtomcrypt/pk/asn1/der/octet/der_length_octet_string.o libtomcrypt/pk/asn1/der/printable_string/der_decode_printable_string.o \
+ libtomcrypt/pk/asn1/der/printable_string/der_encode_printable_string.o libtomcrypt/pk/asn1/der/printable_string/der_length_printable_string.o \
+ libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_ex.o libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_flexi.o \
+ libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_multi.o libtomcrypt/pk/asn1/der/sequence/der_encode_sequence_ex.o \
+ libtomcrypt/pk/asn1/der/sequence/der_encode_sequence_multi.o libtomcrypt/pk/asn1/der/sequence/der_length_sequence.o \
+ libtomcrypt/pk/asn1/der/sequence/der_sequence_free.o libtomcrypt/pk/asn1/der/short_integer/der_decode_short_integer.o \
+ libtomcrypt/pk/asn1/der/short_integer/der_encode_short_integer.o libtomcrypt/pk/asn1/der/short_integer/der_length_short_integer.o \
+ libtomcrypt/pk/asn1/der/utctime/der_decode_utctime.o libtomcrypt/pk/asn1/der/utctime/der_encode_utctime.o \
+ libtomcrypt/pk/asn1/der/utctime/der_length_utctime.o libtomcrypt/pk/asn1/der/utf8/der_decode_utf8_string.o \
+ libtomcrypt/pk/asn1/der/utf8/der_encode_utf8_string.o libtomcrypt/pk/asn1/der/utf8/der_length_utf8_string.o \
+ libtomcrypt/pk/asn1/der/set/der_encode_set.o libtomcrypt/pk/asn1/der/set/der_encode_setof.o \
+ libtomcrypt/pk/rsa/rsa_decrypt_key.o libtomcrypt/pk/rsa/rsa_encrypt_key.o libtomcrypt/pk/rsa/rsa_export.o \
+ libtomcrypt/pk/rsa/rsa_exptmod.o libtomcrypt/pk/rsa/rsa_free.o libtomcrypt/pk/rsa/rsa_import.o \
+ libtomcrypt/pk/rsa/rsa_make_key.o libtomcrypt/pk/rsa/rsa_sign_hash.o libtomcrypt/pk/rsa/rsa_verify_hash.o \
+ libtomcrypt/pk/pkcs1/pkcs_1_i2osp.o libtomcrypt/pk/pkcs1/pkcs_1_mgf1.o libtomcrypt/pk/pkcs1/pkcs_1_oaep_decode.o \
+ libtomcrypt/pk/pkcs1/pkcs_1_oaep_encode.o libtomcrypt/pk/pkcs1/pkcs_1_os2ip.o libtomcrypt/pk/pkcs1/pkcs_1_pss_decode.o \
+ libtomcrypt/pk/pkcs1/pkcs_1_pss_encode.o libtomcrypt/pk/pkcs1/pkcs_1_v1_5_decode.o libtomcrypt/pk/pkcs1/pkcs_1_v1_5_encode.o \
+ libtomcrypt/misc/pk_get_oid.o libtomcrypt/pk/asn1/der/x509/der_encode_subject_public_key_info.o \
+ libtomcrypt/pk/asn1/der/x509/der_decode_subject_public_key_info.o
+
cryptodev-objs := cryptodev_main.o cryptodev_cipher.o ncr-limits.o \
- utils.o $(TOMMATH_OBJECTS)
+ utils.o $(TOMMATH_OBJECTS) \
+ $(TOMCRYPT_OBJECTS)


obj-$(CONFIG_CRYPTO_USERSPACE) += cryptodev.o
diff --git a/crypto/userspace/libtomcrypt/hashes/crypt_hash_is_valid.c b/crypto/userspace/libtomcrypt/hashes/crypt_hash_is_valid.c
new file mode 100644
index 0000000..d01d418
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/hashes/crypt_hash_is_valid.c
@@ -0,0 +1,30 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file crypt_hash_is_valid.c
+ Determine if hash is valid, Tom St Denis
+*/
+
+/*
+ Test if a hash index is valid
+ @param idx The hash to search for
+ @return CRYPT_OK if valid
+*/
+int hash_is_valid(const struct algo_properties_st *hash)
+{
+ return CRYPT_OK;
+}
+
+/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_hash_is_valid.c,v $ */
+/* $Revision: 1.6 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/hashes/hash_get_oid.c b/crypto/userspace/libtomcrypt/hashes/hash_get_oid.c
new file mode 100644
index 0000000..39f4372
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/hashes/hash_get_oid.c
@@ -0,0 +1,78 @@
+/* LibTomCrypt, modular cryptographic library
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ */
+#include "tomcrypt.h"
+#include <ncr-int.h>
+
+/*
+ Returns the OID of the hash.
+ @param idx The hash identifier of the hash to search for
+ @return CRYPT_OK if valid
+*/
+
+static const oid_st sha1_oid = {
+ .OIDlen = 6,
+ .OID = { 1, 3, 14, 3, 2, 26 },
+};
+
+static const oid_st md5_oid = {
+ .OIDlen = 6,
+ .OID = { 1, 2, 840, 113549, 2, 5, },
+};
+
+static const oid_st sha224_oid = {
+ .OIDlen = 9,
+ .OID = { 2, 16, 840, 1, 101, 3, 4, 2, 4, },
+};
+
+static const oid_st sha256_oid = {
+ .OIDlen = 9,
+ .OID = { 2, 16, 840, 1, 101, 3, 4, 2, 1, },
+};
+
+static const oid_st sha384_oid = {
+ .OIDlen = 9,
+ .OID = { 2, 16, 840, 1, 101, 3, 4, 2, 2, },
+};
+
+static const oid_st sha512_oid = {
+ .OIDlen = 9,
+ .OID = { 2, 16, 840, 1, 101, 3, 4, 2, 3, },
+};
+
+int hash_get_oid(const struct algo_properties_st *hash, oid_st *st)
+{
+ switch (hash->algo) {
+ case NCR_ALG_SHA1:
+ memcpy(st, &sha1_oid, sizeof(*st));
+ break;
+ case NCR_ALG_MD5:
+ memcpy(st, &md5_oid, sizeof(*st));
+ break;
+ case NCR_ALG_SHA2_224:
+ memcpy(st, &sha224_oid, sizeof(*st));
+ break;
+ case NCR_ALG_SHA2_256:
+ memcpy(st, &sha256_oid, sizeof(*st));
+ break;
+ case NCR_ALG_SHA2_384:
+ memcpy(st, &sha384_oid, sizeof(*st));
+ break;
+ case NCR_ALG_SHA2_512:
+ memcpy(st, &sha512_oid, sizeof(*st));
+ break;
+ default:
+ return CRYPT_INVALID_ARG;
+ }
+ return CRYPT_OK;
+}
+
+/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_hash_is_valid.c,v $ */
+/* $Revision: 1.6 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/hashes/hash_memory.c b/crypto/userspace/libtomcrypt/hashes/hash_memory.c
new file mode 100644
index 0000000..a416de9
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/hashes/hash_memory.c
@@ -0,0 +1,66 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include <ncr-int.h>
+#include <cryptodev_int.h>
+
+/**
+ @file hash_memory.c
+ Hash memory helper, Tom St Denis
+*/
+
+/**
+ Hash a block of memory and store the digest.
+ @param hash The hash you wish to use
+ @param in The data you wish to hash
+ @param inlen The length of the data to hash (octets)
+ @param out [out] Where to store the digest
+ @param outlen [in/out] Max size and resulting size of the digest
+ @return CRYPT_OK if successful
+*/
+int hash_memory(const struct algo_properties_st *hash, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen)
+{
+ int err;
+ struct hash_data hdata;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ if ((err = hash_is_valid(hash)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (*outlen < hash->digest_size) {
+ *outlen = hash->digest_size;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ err = cryptodev_hash_init( &hdata, hash->kstr, 0, NULL, 0);
+ if (err < 0) {
+ err = CRYPT_INVALID_HASH;
+ goto LBL_ERR;
+ }
+
+ if ((err = _cryptodev_hash_update(&hdata, in, inlen)) < 0) {
+ err = CRYPT_ERROR;
+ goto LBL_ERR;
+ }
+
+ err = cryptodev_hash_final(&hdata, out);
+
+ *outlen = hash->digest_size;
+LBL_ERR:
+ cryptodev_hash_deinit(&hdata);
+
+ return err;
+}
+
diff --git a/crypto/userspace/libtomcrypt/hashes/hash_memory_multi.c b/crypto/userspace/libtomcrypt/hashes/hash_memory_multi.c
new file mode 100644
index 0000000..a914916
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/hashes/hash_memory_multi.c
@@ -0,0 +1,84 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include <stdarg.h>
+#include <ncr-int.h>
+#include <cryptodev_int.h>
+
+/**
+ @file hash_memory_multi.c
+ Hash (multiple buffers) memory helper, Tom St Denis
+*/
+
+/**
+ Hash multiple (non-adjacent) blocks of memory at once.
+ @param hash The hash you wish to use
+ @param out [out] Where to store the digest
+ @param outlen [in/out] Max size and resulting size of the digest
+ @param in The data you wish to hash
+ @param inlen The length of the data to hash (octets)
+ @param ... tuples of (data,len) pairs to hash, terminated with a (NULL,x) (x=don't care)
+ @return CRYPT_OK if successful
+*/
+int hash_memory_multi(const struct algo_properties_st *hash, unsigned char *out, unsigned long *outlen,
+ const unsigned char *in, unsigned long inlen, ...)
+{
+ struct hash_data hdata;
+ int err;
+ va_list args;
+ const unsigned char *curptr;
+ unsigned long curlen;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ if ((err = hash_is_valid(hash)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (*outlen < hash->digest_size) {
+ *outlen = hash->digest_size;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ err = cryptodev_hash_init( &hdata, hash->kstr, 0, NULL, 0);
+ if (err < 0) {
+ err = CRYPT_INVALID_HASH;
+ goto LBL_ERR;
+ }
+
+ va_start(args, inlen);
+ curptr = in;
+ curlen = inlen;
+ for (;;) {
+ /* process buf */
+ if ((err = _cryptodev_hash_update(&hdata, curptr, curlen)) < 0) {
+ err = CRYPT_ERROR;
+ goto LBL_ERR;
+ }
+ /* step to next */
+ curptr = va_arg(args, const unsigned char*);
+ if (curptr == NULL) {
+ break;
+ }
+ curlen = va_arg(args, unsigned long);
+ }
+
+ err = cryptodev_hash_final(&hdata, out);
+
+ *outlen = hash->digest_size;
+LBL_ERR:
+ cryptodev_hash_deinit(&hdata);
+ va_end(args);
+ return err;
+}
+
diff --git a/crypto/userspace/libtomcrypt/headers/tomcrypt_prng.h b/crypto/userspace/libtomcrypt/headers/tomcrypt_prng.h
new file mode 100644
index 0000000..26bf711
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/headers/tomcrypt_prng.h
@@ -0,0 +1,80 @@
+/* ---- PRNG Stuff ---- */
+
+typedef union Prng_state {
+ char dummy[1];
+} prng_state;
+
+/** PRNG descriptor */
+extern struct ltc_prng_descriptor {
+ /** Name of the PRNG */
+ char *name;
+ /** size in bytes of exported state */
+ int export_size;
+ /** Start a PRNG state
+ @param prng [out] The state to initialize
+ @return CRYPT_OK if successful
+ */
+ int (*start)(prng_state *prng);
+ /** Add entropy to the PRNG
+ @param in The entropy
+ @param inlen Length of the entropy (octets)\
+ @param prng The PRNG state
+ @return CRYPT_OK if successful
+ */
+ int (*add_entropy)(const unsigned char *in, unsigned long inlen, prng_state *prng);
+ /** Ready a PRNG state to read from
+ @param prng The PRNG state to ready
+ @return CRYPT_OK if successful
+ */
+ int (*ready)(prng_state *prng);
+ /** Read from the PRNG
+ @param out [out] Where to store the data
+ @param outlen Length of data desired (octets)
+ @param prng The PRNG state to read from
+ @return Number of octets read
+ */
+ unsigned long (*read)(unsigned char *out, unsigned long outlen, prng_state *prng);
+ /** Terminate a PRNG state
+ @param prng The PRNG state to terminate
+ @return CRYPT_OK if successful
+ */
+ int (*done)(prng_state *prng);
+ /** Export a PRNG state
+ @param out [out] The destination for the state
+ @param outlen [in/out] The max size and resulting size of the PRNG state
+ @param prng The PRNG to export
+ @return CRYPT_OK if successful
+ */
+ int (*pexport)(unsigned char *out, unsigned long *outlen, prng_state *prng);
+ /** Import a PRNG state
+ @param in The data to import
+ @param inlen The length of the data to import (octets)
+ @param prng The PRNG to initialize/import
+ @return CRYPT_OK if successful
+ */
+ int (*pimport)(const unsigned char *in, unsigned long inlen, prng_state *prng);
+ /** Self-test the PRNG
+ @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled
+ */
+ int (*test)(void);
+} prng_descriptor[];
+
+int linux_start(prng_state *prng);
+int linux_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng);
+int linux_ready(prng_state *prng);
+unsigned long linux_read(unsigned char *out, unsigned long outlen, prng_state *prng);
+int linux_done(prng_state *prng);
+int linux_export(unsigned char *out, unsigned long *outlen, prng_state *prng);
+int linux_import(const unsigned char *in, unsigned long inlen, prng_state *prng);
+int linux_test(void);
+
+extern const struct ltc_prng_descriptor linux_desc;
+
+int find_prng(const char *name);
+int register_prng(const struct ltc_prng_descriptor *prng);
+int unregister_prng(const struct ltc_prng_descriptor *prng);
+int prng_is_valid(int idx);
+
+/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_prng.h,v $ */
+/* $Revision: 1.9 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/math/rand_prime.c b/crypto/userspace/libtomcrypt/math/rand_prime.c
new file mode 100644
index 0000000..ab73cd0
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/math/rand_prime.c
@@ -0,0 +1,80 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include <linux/slab.h>
+
+/**
+ @file rand_prime.c
+ Generate a random prime, Tom St Denis
+*/
+
+#define USE_BBS 1
+
+int rand_prime(mp_int *N, long len)
+{
+ int err, res, type;
+ unsigned char *buf;
+
+ LTC_ARGCHK(N != NULL);
+
+ /* get type */
+ if (len < 0) {
+ type = USE_BBS;
+ len = -len;
+ } else {
+ type = 0;
+ }
+
+ /* allow sizes between 2 and 512 bytes for a prime size */
+ if (len < 2 || len > 512) {
+ return CRYPT_INVALID_PRIME_SIZE;
+ }
+
+ /* allocate buffer to work with */
+ buf = XCALLOC(1, len);
+ if (buf == NULL) {
+ return CRYPT_MEM;
+ }
+
+ do {
+ /* generate value */
+ get_random_bytes( buf, len);
+
+ /* munge bits */
+ buf[0] |= 0x80 | 0x40;
+ buf[len-1] |= 0x01 | ((type & USE_BBS) ? 0x02 : 0x00);
+
+ /* load value */
+ if ((err = mp_read_unsigned_bin(N, buf, len)) != CRYPT_OK) {
+ XFREE(buf);
+ return err;
+ }
+
+ /* test */
+ if ((err = mp_prime_is_prime(N, 8, &res)) != CRYPT_OK) {
+ XFREE(buf);
+ return err;
+ }
+ } while (res == LTC_MP_NO);
+
+#ifdef LTC_CLEAN_STACK
+ zeromem(buf, len);
+#endif
+
+ XFREE(buf);
+ return CRYPT_OK;
+}
+
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/math/rand_prime.c,v $ */
+/* $Revision: 1.7 $ */
+/* $Date: 2006/12/28 01:27:23 $ */
diff --git a/crypto/userspace/libtomcrypt/misc/crypt/crypt_argchk.c b/crypto/userspace/libtomcrypt/misc/crypt/crypt_argchk.c
new file mode 100644
index 0000000..143b784
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/misc/crypt/crypt_argchk.c
@@ -0,0 +1,28 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file crypt_argchk.c
+ Perform argument checking, Tom St Denis
+*/
+
+#if (ARGTYPE == 0)
+void crypt_argchk(char *v, char *s, int d)
+{
+ printk("LTC_ARGCHK '%s' failure on line %d of file %s\n",
+ v, d, s);
+}
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_argchk.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/misc/pk_get_oid.c b/crypto/userspace/libtomcrypt/misc/pk_get_oid.c
new file mode 100644
index 0000000..197d7ae
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/misc/pk_get_oid.c
@@ -0,0 +1,40 @@
+/* LibTomCrypt, modular cryptographic library
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ */
+#include "tomcrypt.h"
+
+static const oid_st rsa_oid = {
+ .OIDlen = 7,
+ .OID = { 1, 2, 840, 113549, 1, 1, 1 },
+};
+
+static const oid_st dsa_oid = {
+ .OIDlen = 6,
+ .OID = { 1, 2, 840, 10040, 4, 1 },
+};
+
+/*
+ Returns the OID of the public key algorithm.
+ @return CRYPT_OK if valid
+*/
+int pk_get_oid(int pk, oid_st *st)
+{
+ switch (pk) {
+ case PKA_RSA:
+ memcpy(st, &rsa_oid, sizeof(*st));
+ break;
+ case PKA_DSA:
+ memcpy(st, &dsa_oid, sizeof(*st));
+ break;
+ default:
+ return CRYPT_INVALID_ARG;
+ }
+ return CRYPT_OK;
+}
+
diff --git a/crypto/userspace/libtomcrypt/misc/qsort.c b/crypto/userspace/libtomcrypt/misc/qsort.c
new file mode 100644
index 0000000..72f5108
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/misc/qsort.c
@@ -0,0 +1,247 @@
+/* Copyright (C) 1991,1992,1996,1997,1999,2004 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Douglas C. Schmidt ([email protected]).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+/* If you consider tuning this algorithm, you should consult first:
+ Engineering a sort function; Jon Bentley and M. Douglas McIlroy;
+ Software - Practice and Experience; Vol. 23 (11), 1249-1265, 1993. */
+
+#include <tomcrypt.h>
+
+/* Byte-wise swap two items of size SIZE. */
+#define SWAP(a, b, size) \
+ do \
+ { \
+ register size_t __size = (size); \
+ register char *__a = (a), *__b = (b); \
+ do \
+ { \
+ char __tmp = *__a; \
+ *__a++ = *__b; \
+ *__b++ = __tmp; \
+ } while (--__size > 0); \
+ } while (0)
+
+/* Discontinue quicksort algorithm when partition gets below this size.
+ This particular magic number was chosen to work best on a Sun 4/260. */
+#define MAX_THRESH 4
+
+/* Stack node declarations used to store unfulfilled partition obligations. */
+typedef struct
+ {
+ char *lo;
+ char *hi;
+ } stack_node;
+
+/* The next 4 #defines implement a very fast in-line stack abstraction. */
+/* The stack needs log (total_elements) entries (we could even subtract
+ log(MAX_THRESH)). Since total_elements has type size_t, we get as
+ upper bound for log (total_elements):
+ bits per byte (CHAR_BIT) * sizeof(size_t). */
+#define STACK_SIZE (CHAR_BIT * sizeof(size_t))
+#define PUSH(low, high) ((void) ((top->lo = (low)), (top->hi = (high)), ++top))
+#define POP(low, high) ((void) (--top, (low = top->lo), (high = top->hi)))
+#define STACK_NOT_EMPTY (stack < top)
+
+
+/* Order size using quicksort. This implementation incorporates
+ four optimizations discussed in Sedgewick:
+
+ 1. Non-recursive, using an explicit stack of pointer that store the
+ next array partition to sort. To save time, this maximum amount
+ of space required to store an array of SIZE_MAX is allocated on the
+ stack. Assuming a 32-bit (64 bit) integer for size_t, this needs
+ only 32 * sizeof(stack_node) == 256 bytes (for 64 bit: 1024 bytes).
+ Pretty cheap, actually.
+
+ 2. Chose the pivot element using a median-of-three decision tree.
+ This reduces the probability of selecting a bad pivot value and
+ eliminates certain extraneous comparisons.
+
+ 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving
+ insertion sort to order the MAX_THRESH items within each partition.
+ This is a big win, since insertion sort is faster for small, mostly
+ sorted array segments.
+
+ 4. The larger of the two sub-partitions is always pushed onto the
+ stack first, with the algorithm then concentrating on the
+ smaller partition. This *guarantees* no more than log (total_elems)
+ stack size is needed (actually O(1) in this case)! */
+
+typedef int(*__compar_fn_t)(const void *, const void *);
+
+void
+qsort (void *const pbase, size_t total_elems, size_t size,
+ __compar_fn_t cmp)
+{
+ register char *base_ptr = (char *) pbase;
+
+ const size_t max_thresh = MAX_THRESH * size;
+
+ if (total_elems == 0)
+ /* Avoid lossage with unsigned arithmetic below. */
+ return;
+
+ if (total_elems > MAX_THRESH)
+ {
+ char *lo = base_ptr;
+ char *hi = &lo[size * (total_elems - 1)];
+ stack_node stack[STACK_SIZE];
+ stack_node *top = stack;
+
+ PUSH (NULL, NULL);
+
+ while (STACK_NOT_EMPTY)
+ {
+ char *left_ptr;
+ char *right_ptr;
+
+ /* Select median value from among LO, MID, and HI. Rearrange
+ LO and HI so the three values are sorted. This lowers the
+ probability of picking a pathological pivot value and
+ skips a comparison for both the LEFT_PTR and RIGHT_PTR in
+ the while loops. */
+
+ char *mid = lo + size * ((hi - lo) / size >> 1);
+
+ if ((*cmp) ((void *) mid, (void *) lo) < 0)
+ SWAP (mid, lo, size);
+ if ((*cmp) ((void *) hi, (void *) mid) < 0)
+ SWAP (mid, hi, size);
+ else
+ goto jump_over;
+ if ((*cmp) ((void *) mid, (void *) lo) < 0)
+ SWAP (mid, lo, size);
+ jump_over:;
+
+ left_ptr = lo + size;
+ right_ptr = hi - size;
+
+ /* Here's the famous ``collapse the walls'' section of quicksort.
+ Gotta like those tight inner loops! They are the main reason
+ that this algorithm runs much faster than others. */
+ do
+ {
+ while ((*cmp) ((void *) left_ptr, (void *) mid) < 0)
+ left_ptr += size;
+
+ while ((*cmp) ((void *) mid, (void *) right_ptr) < 0)
+ right_ptr -= size;
+
+ if (left_ptr < right_ptr)
+ {
+ SWAP (left_ptr, right_ptr, size);
+ if (mid == left_ptr)
+ mid = right_ptr;
+ else if (mid == right_ptr)
+ mid = left_ptr;
+ left_ptr += size;
+ right_ptr -= size;
+ }
+ else if (left_ptr == right_ptr)
+ {
+ left_ptr += size;
+ right_ptr -= size;
+ break;
+ }
+ }
+ while (left_ptr <= right_ptr);
+
+ /* Set up pointers for next iteration. First determine whether
+ left and right partitions are below the threshold size. If so,
+ ignore one or both. Otherwise, push the larger partition's
+ bounds on the stack and continue sorting the smaller one. */
+
+ if ((size_t) (right_ptr - lo) <= max_thresh)
+ {
+ if ((size_t) (hi - left_ptr) <= max_thresh)
+ /* Ignore both small partitions. */
+ POP (lo, hi);
+ else
+ /* Ignore small left partition. */
+ lo = left_ptr;
+ }
+ else if ((size_t) (hi - left_ptr) <= max_thresh)
+ /* Ignore small right partition. */
+ hi = right_ptr;
+ else if ((right_ptr - lo) > (hi - left_ptr))
+ {
+ /* Push larger left partition indices. */
+ PUSH (lo, right_ptr);
+ lo = left_ptr;
+ }
+ else
+ {
+ /* Push larger right partition indices. */
+ PUSH (left_ptr, hi);
+ hi = right_ptr;
+ }
+ }
+ }
+
+ /* Once the BASE_PTR array is partially sorted by quicksort the rest
+ is completely sorted using insertion sort, since this is efficient
+ for partitions below MAX_THRESH size. BASE_PTR points to the beginning
+ of the array to sort, and END_PTR points at the very last element in
+ the array (*not* one beyond it!). */
+
+ {
+ char *const end_ptr = &base_ptr[size * (total_elems - 1)];
+ char *tmp_ptr = base_ptr;
+ char *thresh = min(end_ptr, base_ptr + max_thresh);
+ register char *run_ptr;
+
+ /* Find smallest element in first threshold and place it at the
+ array's beginning. This is the smallest array element,
+ and the operation speeds up insertion sort's inner loop. */
+
+ for (run_ptr = tmp_ptr + size; run_ptr <= thresh; run_ptr += size)
+ if ((*cmp) ((void *) run_ptr, (void *) tmp_ptr) < 0)
+ tmp_ptr = run_ptr;
+
+ if (tmp_ptr != base_ptr)
+ SWAP (tmp_ptr, base_ptr, size);
+
+ /* Insertion sort, running from left-hand-side up to right-hand-side. */
+
+ run_ptr = base_ptr + size;
+ while ((run_ptr += size) <= end_ptr)
+ {
+ tmp_ptr = run_ptr - size;
+ while ((*cmp) ((void *) run_ptr, (void *) tmp_ptr) < 0)
+ tmp_ptr -= size;
+
+ tmp_ptr += size;
+ if (tmp_ptr != run_ptr)
+ {
+ char *trav;
+
+ trav = run_ptr + size;
+ while (--trav >= run_ptr)
+ {
+ char c = *trav;
+ char *hi, *lo;
+
+ for (hi = lo = trav; (lo -= size) >= tmp_ptr; hi = lo)
+ *hi = *lo;
+ *hi = c;
+ }
+ }
+ }
+ }
+}
diff --git a/crypto/userspace/libtomcrypt/misc/zeromem.c b/crypto/userspace/libtomcrypt/misc/zeromem.c
new file mode 100644
index 0000000..a4bb124
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/misc/zeromem.c
@@ -0,0 +1,34 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file zeromem.c
+ Zero a block of memory, Tom St Denis
+*/
+
+/**
+ Zero a block of memory
+ @param out The destination of the area to zero
+ @param outlen The length of the area to zero (octets)
+*/
+void zeromem(void *out, size_t outlen)
+{
+ unsigned char *mem = out;
+ LTC_ARGCHKVD(out != NULL);
+ while (outlen-- > 0) {
+ *mem++ = 0;
+ }
+}
+
+/* $Source: /cvs/libtom/libtomcrypt/src/misc/zeromem.c,v $ */
+/* $Revision: 1.7 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/bit/der_decode_bit_string.c b/crypto/userspace/libtomcrypt/pk/asn1/der/bit/der_decode_bit_string.c
new file mode 100644
index 0000000..c9f6368
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/bit/der_decode_bit_string.c
@@ -0,0 +1,106 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_decode_bit_string.c
+ ASN.1 DER, encode a BIT STRING, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+#define setbit(v, n) (v=((unsigned char)(v) | (1U << (unsigned char)(n))))
+
+/**
+ Store a BIT STRING
+ @param in The DER encoded BIT STRING
+ @param inlen The size of the DER BIT STRING
+ @param out [out] The array of bits stored (8 per char)
+ @param outlen [in/out] The number of bits stored
+ @return CRYPT_OK if successful
+*/
+int der_decode_bit_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long dlen, blen, x, y;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* packet must be at least 4 bytes */
+ if (inlen < 4) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* check for 0x03 */
+ if ((in[0]&0x1F) != 0x03) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* offset in the data */
+ x = 1;
+
+ /* get the length of the data */
+ if (in[x] & 0x80) {
+ /* long format get number of length bytes */
+ y = in[x++] & 0x7F;
+
+ /* invalid if 0 or > 2 */
+ if (y == 0 || y > 2) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* read the data len */
+ dlen = 0;
+ while (y--) {
+ dlen = (dlen << 8) | (unsigned long)in[x++];
+ }
+ } else {
+ /* short format */
+ dlen = in[x++] & 0x7F;
+ }
+
+ /* is the data len too long or too short? */
+ if ((dlen == 0) || (dlen + x > inlen)) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* get padding count */
+ blen = ((dlen - 1) << 3) - (in[x++] & 7);
+
+ /* too many bits? */
+ if (blen > *outlen) {
+ *outlen = blen;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* decode/store the bits */
+ for (y = 0; y < blen; y++) {
+ if (in[x] & (1 << (7 - (y & 7)))) {
+ setbit(out[y/8], 7-(y%8));
+ }
+ if ((y & 7) == 7) {
+ ++x;
+ }
+ }
+
+ /* we done */
+ *outlen = blen;
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/bit/der_decode_bit_string.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/bit/der_encode_bit_string.c b/crypto/userspace/libtomcrypt/pk/asn1/der/bit/der_encode_bit_string.c
new file mode 100644
index 0000000..d1b6064
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/bit/der_encode_bit_string.c
@@ -0,0 +1,92 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_encode_bit_string.c
+ ASN.1 DER, encode a BIT STRING, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+#define getbit(n, k) (((n) & ( 1 << (k) )) >> (k))
+
+/**
+ Store a BIT STRING
+ @param in The array of bits to store (8 per char)
+ @param inlen The number of bits tostore
+ @param out [out] The destination for the DER encoded BIT STRING
+ @param outlen [in/out] The max size and resulting size of the DER BIT STRING
+ @return CRYPT_OK if successful
+*/
+int der_encode_bit_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long len, x, y;
+ unsigned char buf;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* avoid overflows */
+ if ((err = der_length_bit_string(inlen, &len)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (len > *outlen) {
+ *outlen = len;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* store header (include bit padding count in length) */
+ x = 0;
+ y = (inlen >> 3) + ((inlen&7) ? 1 : 0) + 1;
+
+ out[x++] = 0x03;
+ if (y < 128) {
+ out[x++] = (unsigned char)y;
+ } else if (y < 256) {
+ out[x++] = 0x81;
+ out[x++] = (unsigned char)y;
+ } else if (y < 65536) {
+ out[x++] = 0x82;
+ out[x++] = (unsigned char)((y>>8)&255);
+ out[x++] = (unsigned char)(y&255);
+ }
+
+ /* store number of zero padding bits */
+ out[x++] = (unsigned char)((8 - inlen) & 7);
+
+ /* store the bits in big endian format */
+ for (y = buf = 0; y < inlen; y++) {
+ buf |= (getbit(in[y/8],7-y%8)?1:0) << (7 - (y & 7));
+ if ((y & 7) == 7) {
+ out[x++] = buf;
+ buf = 0;
+ }
+ }
+ /* store last byte */
+ if (inlen & 7) {
+ out[x++] = buf;
+ }
+
+ *outlen = x;
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/bit/der_encode_bit_string.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/bit/der_length_bit_string.c b/crypto/userspace/libtomcrypt/pk/asn1/der/bit/der_length_bit_string.c
new file mode 100644
index 0000000..3b7a8e1
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/bit/der_length_bit_string.c
@@ -0,0 +1,54 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_length_bit_string.c
+ ASN.1 DER, get length of BIT STRING, Tom St Denis
+*/
+
+#ifdef LTC_DER
+/**
+ Gets length of DER encoding of BIT STRING
+ @param nbits The number of bits in the string to encode
+ @param outlen [out] The length of the DER encoding for the given string
+ @return CRYPT_OK if successful
+*/
+int der_length_bit_string(unsigned long nbits, unsigned long *outlen)
+{
+ unsigned long nbytes;
+ LTC_ARGCHK(outlen != NULL);
+
+ /* get the number of the bytes */
+ nbytes = (nbits >> 3) + ((nbits & 7) ? 1 : 0) + 1;
+
+ if (nbytes < 128) {
+ /* 03 LL PP DD DD DD ... */
+ *outlen = 2 + nbytes;
+ } else if (nbytes < 256) {
+ /* 03 81 LL PP DD DD DD ... */
+ *outlen = 3 + nbytes;
+ } else if (nbytes < 65536) {
+ /* 03 82 LL LL PP DD DD DD ... */
+ *outlen = 4 + nbytes;
+ } else {
+ return CRYPT_INVALID_ARG;
+ }
+
+ return CRYPT_OK;
+}
+
+#endif
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/bit/der_length_bit_string.c,v $ */
+/* $Revision: 1.3 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/boolean/der_decode_boolean.c b/crypto/userspace/libtomcrypt/pk/asn1/der/boolean/der_decode_boolean.c
new file mode 100644
index 0000000..f374aa6
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/boolean/der_decode_boolean.c
@@ -0,0 +1,47 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_decode_boolean.c
+ ASN.1 DER, decode a BOOLEAN, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Read a BOOLEAN
+ @param in The destination for the DER encoded BOOLEAN
+ @param inlen The size of the DER BOOLEAN
+ @param out [out] The boolean to decode
+ @return CRYPT_OK if successful
+*/
+int der_decode_boolean(const unsigned char *in, unsigned long inlen,
+ int *out)
+{
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ if (inlen != 3 || in[0] != 0x01 || in[1] != 0x01 || (in[2] != 0x00 && in[2] != 0xFF)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ *out = (in[2]==0xFF) ? 1 : 0;
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/boolean/der_decode_boolean.c,v $ */
+/* $Revision: 1.2 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/boolean/der_encode_boolean.c b/crypto/userspace/libtomcrypt/pk/asn1/der/boolean/der_encode_boolean.c
new file mode 100644
index 0000000..df497bf
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/boolean/der_encode_boolean.c
@@ -0,0 +1,51 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_encode_boolean.c
+ ASN.1 DER, encode a BOOLEAN, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Store a BOOLEAN
+ @param in The boolean to encode
+ @param out [out] The destination for the DER encoded BOOLEAN
+ @param outlen [in/out] The max size and resulting size of the DER BOOLEAN
+ @return CRYPT_OK if successful
+*/
+int der_encode_boolean(int in,
+ unsigned char *out, unsigned long *outlen)
+{
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ if (*outlen < 3) {
+ *outlen = 3;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ *outlen = 3;
+ out[0] = 0x01;
+ out[1] = 0x01;
+ out[2] = in ? 0xFF : 0x00;
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/boolean/der_encode_boolean.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/boolean/der_length_boolean.c b/crypto/userspace/libtomcrypt/pk/asn1/der/boolean/der_length_boolean.c
new file mode 100644
index 0000000..aa3e03d
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/boolean/der_length_boolean.c
@@ -0,0 +1,35 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_length_boolean.c
+ ASN.1 DER, get length of a BOOLEAN, Tom St Denis
+*/
+
+#ifdef LTC_DER
+/**
+ Gets length of DER encoding of a BOOLEAN
+ @param outlen [out] The length of the DER encoding
+ @return CRYPT_OK if successful
+*/
+int der_length_boolean(unsigned long *outlen)
+{
+ LTC_ARGCHK(outlen != NULL);
+ *outlen = 3;
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/boolean/der_length_boolean.c,v $ */
+/* $Revision: 1.3 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/choice/der_decode_choice.c b/crypto/userspace/libtomcrypt/pk/asn1/der/choice/der_decode_choice.c
new file mode 100644
index 0000000..277c731
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/choice/der_decode_choice.c
@@ -0,0 +1,182 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_decode_choice.c
+ ASN.1 DER, decode a CHOICE, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/**
+ Decode a CHOICE
+ @param in The DER encoded input
+ @param inlen [in/out] The size of the input and resulting size of read type
+ @param list The list of items to decode
+ @param outlen The number of items in the list
+ @return CRYPT_OK on success
+*/
+int der_decode_choice(const unsigned char *in, unsigned long *inlen,
+ ltc_asn1_list *list, unsigned long outlen)
+{
+ unsigned long size, x, z;
+ void *data;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(inlen != NULL);
+ LTC_ARGCHK(list != NULL);
+
+ /* get blk size */
+ if (*inlen < 2) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* set all of the "used" flags to zero */
+ for (x = 0; x < outlen; x++) {
+ list[x].used = 0;
+ }
+
+ /* now scan until we have a winner */
+ for (x = 0; x < outlen; x++) {
+ size = list[x].size;
+ data = list[x].data;
+
+ switch (list[x].type) {
+ case LTC_ASN1_INTEGER:
+ if (der_decode_integer(in, *inlen, data) == CRYPT_OK) {
+ if (der_length_integer(data, &z) == CRYPT_OK) {
+ list[x].used = 1;
+ *inlen = z;
+ return CRYPT_OK;
+ }
+ }
+ break;
+
+ case LTC_ASN1_SHORT_INTEGER:
+ if (der_decode_short_integer(in, *inlen, data) == CRYPT_OK) {
+ if (der_length_short_integer(size, &z) == CRYPT_OK) {
+ list[x].used = 1;
+ *inlen = z;
+ return CRYPT_OK;
+ }
+ }
+ break;
+
+ case LTC_ASN1_BIT_STRING:
+ if (der_decode_bit_string(in, *inlen, data, &size) == CRYPT_OK) {
+ if (der_length_bit_string(size, &z) == CRYPT_OK) {
+ list[x].used = 1;
+ list[x].size = size;
+ *inlen = z;
+ return CRYPT_OK;
+ }
+ }
+ break;
+
+ case LTC_ASN1_OCTET_STRING:
+ if (der_decode_octet_string(in, *inlen, data, &size) == CRYPT_OK) {
+ if (der_length_octet_string(size, &z) == CRYPT_OK) {
+ list[x].used = 1;
+ list[x].size = size;
+ *inlen = z;
+ return CRYPT_OK;
+ }
+ }
+ break;
+
+ case LTC_ASN1_NULL:
+ if (*inlen == 2 && in[x] == 0x05 && in[x+1] == 0x00) {
+ *inlen = 2;
+ list[x].used = 1;
+ return CRYPT_OK;
+ }
+ break;
+
+ case LTC_ASN1_OBJECT_IDENTIFIER:
+ if (der_decode_object_identifier(in, *inlen, data, &size) == CRYPT_OK) {
+ if (der_length_object_identifier(data, size, &z) == CRYPT_OK) {
+ list[x].used = 1;
+ list[x].size = size;
+ *inlen = z;
+ return CRYPT_OK;
+ }
+ }
+ break;
+
+ case LTC_ASN1_IA5_STRING:
+ if (der_decode_ia5_string(in, *inlen, data, &size) == CRYPT_OK) {
+ if (der_length_ia5_string(data, size, &z) == CRYPT_OK) {
+ list[x].used = 1;
+ list[x].size = size;
+ *inlen = z;
+ return CRYPT_OK;
+ }
+ }
+ break;
+
+
+ case LTC_ASN1_PRINTABLE_STRING:
+ if (der_decode_printable_string(in, *inlen, data, &size) == CRYPT_OK) {
+ if (der_length_printable_string(data, size, &z) == CRYPT_OK) {
+ list[x].used = 1;
+ list[x].size = size;
+ *inlen = z;
+ return CRYPT_OK;
+ }
+ }
+ break;
+
+ case LTC_ASN1_UTF8_STRING:
+ if (der_decode_utf8_string(in, *inlen, data, &size) == CRYPT_OK) {
+ if (der_length_utf8_string(data, size, &z) == CRYPT_OK) {
+ list[x].used = 1;
+ list[x].size = size;
+ *inlen = z;
+ return CRYPT_OK;
+ }
+ }
+ break;
+
+ case LTC_ASN1_UTCTIME:
+ z = *inlen;
+ if (der_decode_utctime(in, &z, data) == CRYPT_OK) {
+ list[x].used = 1;
+ *inlen = z;
+ return CRYPT_OK;
+ }
+ break;
+
+ case LTC_ASN1_SET:
+ case LTC_ASN1_SETOF:
+ case LTC_ASN1_SEQUENCE:
+ if (der_decode_sequence(in, *inlen, data, size) == CRYPT_OK) {
+ if (der_length_sequence(data, size, &z) == CRYPT_OK) {
+ list[x].used = 1;
+ *inlen = z;
+ return CRYPT_OK;
+ }
+ }
+ break;
+
+ default:
+ return CRYPT_INVALID_ARG;
+ }
+ }
+
+ return CRYPT_INVALID_PACKET;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/choice/der_decode_choice.c,v $ */
+/* $Revision: 1.9 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/ia5/der_decode_ia5_string.c b/crypto/userspace/libtomcrypt/pk/asn1/der/ia5/der_decode_ia5_string.c
new file mode 100644
index 0000000..001477b
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/ia5/der_decode_ia5_string.c
@@ -0,0 +1,96 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_decode_ia5_string.c
+ ASN.1 DER, encode a IA5 STRING, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Store a IA5 STRING
+ @param in The DER encoded IA5 STRING
+ @param inlen The size of the DER IA5 STRING
+ @param out [out] The array of octets stored (one per char)
+ @param outlen [in/out] The number of octets stored
+ @return CRYPT_OK if successful
+*/
+int der_decode_ia5_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long x, y, len;
+ int t;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* must have header at least */
+ if (inlen < 2) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* check for 0x16 */
+ if ((in[0] & 0x1F) != 0x16) {
+ return CRYPT_INVALID_PACKET;
+ }
+ x = 1;
+
+ /* decode the length */
+ if (in[x] & 0x80) {
+ /* valid # of bytes in length are 1,2,3 */
+ y = in[x] & 0x7F;
+ if ((y == 0) || (y > 3) || ((x + y) > inlen)) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* read the length in */
+ len = 0;
+ ++x;
+ while (y--) {
+ len = (len << 8) | in[x++];
+ }
+ } else {
+ len = in[x++] & 0x7F;
+ }
+
+ /* is it too long? */
+ if (len > *outlen) {
+ *outlen = len;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ if (len + x > inlen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* read the data */
+ for (y = 0; y < len; y++) {
+ t = der_ia5_value_decode(in[x++]);
+ if (t == -1) {
+ return CRYPT_INVALID_ARG;
+ }
+ out[y] = t;
+ }
+
+ *outlen = y;
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/ia5/der_decode_ia5_string.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/ia5/der_encode_ia5_string.c b/crypto/userspace/libtomcrypt/pk/asn1/der/ia5/der_encode_ia5_string.c
new file mode 100644
index 0000000..82ed466
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/ia5/der_encode_ia5_string.c
@@ -0,0 +1,85 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_encode_ia5_string.c
+ ASN.1 DER, encode a IA5 STRING, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/**
+ Store an IA5 STRING
+ @param in The array of IA5 to store (one per char)
+ @param inlen The number of IA5 to store
+ @param out [out] The destination for the DER encoded IA5 STRING
+ @param outlen [in/out] The max size and resulting size of the DER IA5 STRING
+ @return CRYPT_OK if successful
+*/
+int der_encode_ia5_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long x, y, len;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* get the size */
+ if ((err = der_length_ia5_string(in, inlen, &len)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* too big? */
+ if (len > *outlen) {
+ *outlen = len;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* encode the header+len */
+ x = 0;
+ out[x++] = 0x16;
+ if (inlen < 128) {
+ out[x++] = (unsigned char)inlen;
+ } else if (inlen < 256) {
+ out[x++] = 0x81;
+ out[x++] = (unsigned char)inlen;
+ } else if (inlen < 65536UL) {
+ out[x++] = 0x82;
+ out[x++] = (unsigned char)((inlen>>8)&255);
+ out[x++] = (unsigned char)(inlen&255);
+ } else if (inlen < 16777216UL) {
+ out[x++] = 0x83;
+ out[x++] = (unsigned char)((inlen>>16)&255);
+ out[x++] = (unsigned char)((inlen>>8)&255);
+ out[x++] = (unsigned char)(inlen&255);
+ } else {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* store octets */
+ for (y = 0; y < inlen; y++) {
+ out[x++] = der_ia5_char_encode(in[y]);
+ }
+
+ /* retun length */
+ *outlen = x;
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/ia5/der_encode_ia5_string.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/ia5/der_length_ia5_string.c b/crypto/userspace/libtomcrypt/pk/asn1/der/ia5/der_length_ia5_string.c
new file mode 100644
index 0000000..4d60f8e
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/ia5/der_length_ia5_string.c
@@ -0,0 +1,194 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_length_ia5_string.c
+ ASN.1 DER, get length of IA5 STRING, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+static const struct {
+ int code, value;
+} ia5_table[] = {
+{ '\0', 0 },
+{ '\a', 7 },
+{ '\b', 8 },
+{ '\t', 9 },
+{ '\n', 10 },
+{ '\f', 12 },
+{ '\r', 13 },
+{ ' ', 32 },
+{ '!', 33 },
+{ '"', 34 },
+{ '#', 35 },
+{ '$', 36 },
+{ '%', 37 },
+{ '&', 38 },
+{ '\'', 39 },
+{ '(', 40 },
+{ ')', 41 },
+{ '*', 42 },
+{ '+', 43 },
+{ ',', 44 },
+{ '-', 45 },
+{ '.', 46 },
+{ '/', 47 },
+{ '0', 48 },
+{ '1', 49 },
+{ '2', 50 },
+{ '3', 51 },
+{ '4', 52 },
+{ '5', 53 },
+{ '6', 54 },
+{ '7', 55 },
+{ '8', 56 },
+{ '9', 57 },
+{ ':', 58 },
+{ ';', 59 },
+{ '<', 60 },
+{ '=', 61 },
+{ '>', 62 },
+{ '?', 63 },
+{ '@', 64 },
+{ 'A', 65 },
+{ 'B', 66 },
+{ 'C', 67 },
+{ 'D', 68 },
+{ 'E', 69 },
+{ 'F', 70 },
+{ 'G', 71 },
+{ 'H', 72 },
+{ 'I', 73 },
+{ 'J', 74 },
+{ 'K', 75 },
+{ 'L', 76 },
+{ 'M', 77 },
+{ 'N', 78 },
+{ 'O', 79 },
+{ 'P', 80 },
+{ 'Q', 81 },
+{ 'R', 82 },
+{ 'S', 83 },
+{ 'T', 84 },
+{ 'U', 85 },
+{ 'V', 86 },
+{ 'W', 87 },
+{ 'X', 88 },
+{ 'Y', 89 },
+{ 'Z', 90 },
+{ '[', 91 },
+{ '\\', 92 },
+{ ']', 93 },
+{ '^', 94 },
+{ '_', 95 },
+{ '`', 96 },
+{ 'a', 97 },
+{ 'b', 98 },
+{ 'c', 99 },
+{ 'd', 100 },
+{ 'e', 101 },
+{ 'f', 102 },
+{ 'g', 103 },
+{ 'h', 104 },
+{ 'i', 105 },
+{ 'j', 106 },
+{ 'k', 107 },
+{ 'l', 108 },
+{ 'm', 109 },
+{ 'n', 110 },
+{ 'o', 111 },
+{ 'p', 112 },
+{ 'q', 113 },
+{ 'r', 114 },
+{ 's', 115 },
+{ 't', 116 },
+{ 'u', 117 },
+{ 'v', 118 },
+{ 'w', 119 },
+{ 'x', 120 },
+{ 'y', 121 },
+{ 'z', 122 },
+{ '{', 123 },
+{ '|', 124 },
+{ '}', 125 },
+{ '~', 126 }
+};
+
+int der_ia5_char_encode(int c)
+{
+ int x;
+ for (x = 0; x < (int)(sizeof(ia5_table)/sizeof(ia5_table[0])); x++) {
+ if (ia5_table[x].code == c) {
+ return ia5_table[x].value;
+ }
+ }
+ return -1;
+}
+
+int der_ia5_value_decode(int v)
+{
+ int x;
+ for (x = 0; x < (int)(sizeof(ia5_table)/sizeof(ia5_table[0])); x++) {
+ if (ia5_table[x].value == v) {
+ return ia5_table[x].code;
+ }
+ }
+ return -1;
+}
+
+/**
+ Gets length of DER encoding of IA5 STRING
+ @param octets The values you want to encode
+ @param noctets The number of octets in the string to encode
+ @param outlen [out] The length of the DER encoding for the given string
+ @return CRYPT_OK if successful
+*/
+int der_length_ia5_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen)
+{
+ unsigned long x;
+
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(octets != NULL);
+
+ /* scan string for validity */
+ for (x = 0; x < noctets; x++) {
+ if (der_ia5_char_encode(octets[x]) == -1) {
+ return CRYPT_INVALID_ARG;
+ }
+ }
+
+ if (noctets < 128) {
+ /* 16 LL DD DD DD ... */
+ *outlen = 2 + noctets;
+ } else if (noctets < 256) {
+ /* 16 81 LL DD DD DD ... */
+ *outlen = 3 + noctets;
+ } else if (noctets < 65536UL) {
+ /* 16 82 LL LL DD DD DD ... */
+ *outlen = 4 + noctets;
+ } else if (noctets < 16777216UL) {
+ /* 16 83 LL LL LL DD DD DD ... */
+ *outlen = 5 + noctets;
+ } else {
+ return CRYPT_INVALID_ARG;
+ }
+
+ return CRYPT_OK;
+}
+
+#endif
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/ia5/der_length_ia5_string.c,v $ */
+/* $Revision: 1.3 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/integer/der_decode_integer.c b/crypto/userspace/libtomcrypt/pk/asn1/der/integer/der_decode_integer.c
new file mode 100644
index 0000000..d7b13cf
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/integer/der_decode_integer.c
@@ -0,0 +1,110 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_decode_integer.c
+ ASN.1 DER, decode an integer, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Read a mp_int integer
+ @param in The DER encoded data
+ @param inlen Size of DER encoded data
+ @param num The first mp_int to decode
+ @return CRYPT_OK if successful
+*/
+int der_decode_integer(const unsigned char *in, unsigned long inlen, mp_int_t num)
+{
+ unsigned long x, y, z;
+ int err;
+
+ LTC_ARGCHK(num != NULL);
+ LTC_ARGCHK(in != NULL);
+
+ /* min DER INTEGER is 0x02 01 00 == 0 */
+ if (inlen < (1 + 1 + 1)) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* ok expect 0x02 when we AND with 0001 1111 [1F] */
+ x = 0;
+ if ((in[x++] & 0x1F) != 0x02) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* now decode the len stuff */
+ z = in[x++];
+
+ if ((z & 0x80) == 0x00) {
+ /* short form */
+
+ /* will it overflow? */
+ if (x + z > inlen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* no so read it */
+ if ((err = mp_read_unsigned_bin(num, (unsigned char *)in + x, z)) != CRYPT_OK) {
+ return err;
+ }
+ } else {
+ /* long form */
+ z &= 0x7F;
+
+ /* will number of length bytes overflow? (or > 4) */
+ if (((x + z) > inlen) || (z > 4) || (z == 0)) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* now read it in */
+ y = 0;
+ while (z--) {
+ y = ((unsigned long)(in[x++])) | (y << 8);
+ }
+
+ /* now will reading y bytes overrun? */
+ if ((x + y) > inlen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* no so read it */
+ if ((err = mp_read_unsigned_bin(num, (unsigned char *)in + x, y)) != CRYPT_OK) {
+ return err;
+ }
+ }
+
+ /* see if it's negative */
+ if (in[x] & 0x80) {
+ mp_int tmp;
+ if (mp_init(&tmp) != CRYPT_OK) {
+ return CRYPT_MEM;
+ }
+
+ if (mp_2expt(&tmp, mp_count_bits(num)) != CRYPT_OK || mp_sub(num, &tmp, num) != CRYPT_OK) {
+ mp_clear(&tmp);
+ return CRYPT_MEM;
+ }
+ mp_clear(&tmp);
+ }
+
+ return CRYPT_OK;
+
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/integer/der_decode_integer.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/integer/der_encode_integer.c b/crypto/userspace/libtomcrypt/pk/asn1/der/integer/der_encode_integer.c
new file mode 100644
index 0000000..830446a
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/integer/der_encode_integer.c
@@ -0,0 +1,130 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_encode_integer.c
+ ASN.1 DER, encode an integer, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/* Exports a positive bignum as DER format (upto 2^32 bytes in size) */
+/**
+ Store a mp_int integer
+ @param num The first mp_int to encode
+ @param out [out] The destination for the DER encoded integers
+ @param outlen [in/out] The max size and resulting size of the DER encoded integers
+ @return CRYPT_OK if successful
+*/
+int der_encode_integer(mp_int_t num, unsigned char *out, unsigned long *outlen)
+{
+ unsigned long tmplen, y;
+ int err, leading_zero;
+
+ LTC_ARGCHK(num != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* find out how big this will be */
+ if ((err = der_length_integer(num, &tmplen)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (*outlen < tmplen) {
+ *outlen = tmplen;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ if (mp_cmp_d(num, 0) != LTC_MP_LT) {
+ /* we only need a leading zero if the msb of the first byte is one */
+ if ((mp_count_bits(num) & 7) == 0 || mp_iszero(num) == LTC_MP_YES) {
+ leading_zero = 1;
+ } else {
+ leading_zero = 0;
+ }
+
+ /* get length of num in bytes (plus 1 since we force the msbyte to zero) */
+ y = mp_unsigned_bin_size(num) + leading_zero;
+ } else {
+ leading_zero = 0;
+ y = mp_count_bits(num);
+ y = y + (8 - (y & 7));
+ y = y >> 3;
+ if (((mp_cnt_lsb(num)+1)==mp_count_bits(num)) && ((mp_count_bits(num)&7)==0)) --y;
+ }
+
+ /* now store initial data */
+ *out++ = 0x02;
+ if (y < 128) {
+ /* short form */
+ *out++ = (unsigned char)y;
+ } else if (y < 256) {
+ *out++ = 0x81;
+ *out++ = (unsigned char)y;
+ } else if (y < 65536UL) {
+ *out++ = 0x82;
+ *out++ = (unsigned char)((y>>8)&255);
+ *out++ = (unsigned char)y;
+ } else if (y < 16777216UL) {
+ *out++ = 0x83;
+ *out++ = (unsigned char)((y>>16)&255);
+ *out++ = (unsigned char)((y>>8)&255);
+ *out++ = (unsigned char)y;
+ } else {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* now store msbyte of zero if num is non-zero */
+ if (leading_zero) {
+ *out++ = 0x00;
+ }
+
+ /* if it's not zero store it as big endian */
+ if (mp_cmp_d(num, 0) == LTC_MP_GT) {
+ /* now store the mpint */
+ if ((err = mp_to_unsigned_bin(num, out)) != CRYPT_OK) {
+ return err;
+ }
+ } else if (mp_iszero(num) != LTC_MP_YES) {
+ mp_int tmp;
+
+ /* negative */
+ if (mp_init(&tmp) != CRYPT_OK) {
+ return CRYPT_MEM;
+ }
+
+ /* 2^roundup and subtract */
+ y = mp_count_bits(num);
+ y = y + (8 - (y & 7));
+ if (((mp_cnt_lsb(num)+1)==mp_count_bits(num)) && ((mp_count_bits(num)&7)==0)) y -= 8;
+ if (mp_2expt(&tmp, y) != CRYPT_OK || mp_add(&tmp, num, &tmp) != CRYPT_OK) {
+ mp_clear(&tmp);
+ return CRYPT_MEM;
+ }
+ if ((err = mp_to_unsigned_bin(&tmp, out)) != CRYPT_OK) {
+ mp_clear(&tmp);
+ return err;
+ }
+ mp_clear(&tmp);
+ }
+
+ /* we good */
+ *outlen = tmplen;
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/integer/der_encode_integer.c,v $ */
+/* $Revision: 1.9 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/integer/der_length_integer.c b/crypto/userspace/libtomcrypt/pk/asn1/der/integer/der_length_integer.c
new file mode 100644
index 0000000..40addd5
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/integer/der_length_integer.c
@@ -0,0 +1,82 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_length_integer.c
+ ASN.1 DER, get length of encoding, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+/**
+ Gets length of DER encoding of num
+ @param num The int to get the size of
+ @param outlen [out] The length of the DER encoding for the given integer
+ @return CRYPT_OK if successful
+*/
+int der_length_integer(mp_int_t num, unsigned long *outlen)
+{
+ unsigned long z, len;
+ int leading_zero;
+
+ LTC_ARGCHK(num != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ if (mp_cmp_d(num, 0) != LTC_MP_LT) {
+ /* positive */
+
+ /* we only need a leading zero if the msb of the first byte is one */
+ if ((mp_count_bits(num) & 7) == 0 || mp_iszero(num) == LTC_MP_YES) {
+ leading_zero = 1;
+ } else {
+ leading_zero = 0;
+ }
+
+ /* size for bignum */
+ z = len = leading_zero + mp_unsigned_bin_size(num);
+ } else {
+ /* it's negative */
+ /* find power of 2 that is a multiple of eight and greater than count bits */
+ leading_zero = 0;
+ z = mp_count_bits(num);
+ z = z + (8 - (z & 7));
+ if (((mp_cnt_lsb(num)+1)==mp_count_bits(num)) && ((mp_count_bits(num)&7)==0)) --z;
+ len = z = z >> 3;
+ }
+
+ /* now we need a length */
+ if (z < 128) {
+ /* short form */
+ ++len;
+ } else {
+ /* long form (relies on z != 0), assumes length bytes < 128 */
+ ++len;
+
+ while (z) {
+ ++len;
+ z >>= 8;
+ }
+ }
+
+ /* we need a 0x02 to indicate it's INTEGER */
+ ++len;
+
+ /* return length */
+ *outlen = len;
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/integer/der_length_integer.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/object_identifier/der_decode_object_identifier.c b/crypto/userspace/libtomcrypt/pk/asn1/der/object_identifier/der_decode_object_identifier.c
new file mode 100644
index 0000000..cdd296d
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/object_identifier/der_decode_object_identifier.c
@@ -0,0 +1,99 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_decode_object_identifier.c
+ ASN.1 DER, Decode Object Identifier, Tom St Denis
+*/
+
+#ifdef LTC_DER
+/**
+ Decode OID data and store the array of integers in words
+ @param in The OID DER encoded data
+ @param inlen The length of the OID data
+ @param words [out] The destination of the OID words
+ @param outlen [in/out] The number of OID words
+ @return CRYPT_OK if successful
+*/
+int der_decode_object_identifier(const unsigned char *in, unsigned long inlen,
+ unsigned long *words, unsigned long *outlen)
+{
+ unsigned long x, y, t, len;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(words != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* header is at least 3 bytes */
+ if (inlen < 3) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* must be room for at least two words */
+ if (*outlen < 2) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* decode the packet header */
+ x = 0;
+ if ((in[x++] & 0x1F) != 0x06) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* get the length */
+ if (in[x] < 128) {
+ len = in[x++];
+ } else {
+ if (in[x] < 0x81 || in[x] > 0x82) {
+ return CRYPT_INVALID_PACKET;
+ }
+ y = in[x++] & 0x7F;
+ len = 0;
+ while (y--) {
+ len = (len << 8) | (unsigned long)in[x++];
+ }
+ }
+
+ if (len < 1 || (len + x) > inlen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* decode words */
+ y = 0;
+ t = 0;
+ while (len--) {
+ t = (t << 7) | (in[x] & 0x7F);
+ if (!(in[x++] & 0x80)) {
+ /* store t */
+ if (y >= *outlen) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+ if (y == 0) {
+ words[0] = t / 40;
+ words[1] = t % 40;
+ y = 2;
+ } else {
+ words[y++] = t;
+ }
+ t = 0;
+ }
+ }
+
+ *outlen = y;
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/object_identifier/der_decode_object_identifier.c,v $ */
+/* $Revision: 1.6 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/object_identifier/der_encode_object_identifier.c b/crypto/userspace/libtomcrypt/pk/asn1/der/object_identifier/der_encode_object_identifier.c
new file mode 100644
index 0000000..b26ebdf
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/object_identifier/der_encode_object_identifier.c
@@ -0,0 +1,111 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_encode_object_identifier.c
+ ASN.1 DER, Encode Object Identifier, Tom St Denis
+*/
+
+#ifdef LTC_DER
+/**
+ Encode an OID
+ @param words The words to encode (upto 32-bits each)
+ @param nwords The number of words in the OID
+ @param out [out] Destination of OID data
+ @param outlen [in/out] The max and resulting size of the OID
+ @return CRYPT_OK if successful
+*/
+int der_encode_object_identifier(unsigned long *words, unsigned long nwords,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long i, x, y, z, t, mask, wordbuf;
+ int err;
+
+ LTC_ARGCHK(words != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* check length */
+ if ((err = der_length_object_identifier(words, nwords, &x)) != CRYPT_OK) {
+ return err;
+ }
+ if (x > *outlen) {
+ *outlen = x;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* compute length to store OID data */
+ z = 0;
+ wordbuf = words[0] * 40 + words[1];
+ for (y = 1; y < nwords; y++) {
+ t = der_object_identifier_bits(wordbuf);
+ z += t/7 + ((t%7) ? 1 : 0) + (wordbuf == 0 ? 1 : 0);
+ if (y < nwords - 1) {
+ wordbuf = words[y + 1];
+ }
+ }
+
+ /* store header + length */
+ x = 0;
+ out[x++] = 0x06;
+ if (z < 128) {
+ out[x++] = (unsigned char)z;
+ } else if (z < 256) {
+ out[x++] = 0x81;
+ out[x++] = (unsigned char)z;
+ } else if (z < 65536UL) {
+ out[x++] = 0x82;
+ out[x++] = (unsigned char)((z>>8)&255);
+ out[x++] = (unsigned char)(z&255);
+ } else {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* store first byte */
+ wordbuf = words[0] * 40 + words[1];
+ for (i = 1; i < nwords; i++) {
+ /* store 7 bit words in little endian */
+ t = wordbuf & 0xFFFFFFFF;
+ if (t) {
+ y = x;
+ mask = 0;
+ while (t) {
+ out[x++] = (unsigned char)((t & 0x7F) | mask);
+ t >>= 7;
+ mask |= 0x80; /* upper bit is set on all but the last byte */
+ }
+ /* now swap bytes y...x-1 */
+ z = x - 1;
+ while (y < z) {
+ t = out[y]; out[y] = out[z]; out[z] = (unsigned char)t;
+ ++y;
+ --z;
+ }
+ } else {
+ /* zero word */
+ out[x++] = 0x00;
+ }
+
+ if (i < nwords - 1) {
+ wordbuf = words[i + 1];
+ }
+ }
+
+ *outlen = x;
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/object_identifier/der_encode_object_identifier.c,v $ */
+/* $Revision: 1.7 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/object_identifier/der_length_object_identifier.c b/crypto/userspace/libtomcrypt/pk/asn1/der/object_identifier/der_length_object_identifier.c
new file mode 100644
index 0000000..ada54ab
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/object_identifier/der_length_object_identifier.c
@@ -0,0 +1,89 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_length_object_identifier.c
+ ASN.1 DER, get length of Object Identifier, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+unsigned long der_object_identifier_bits(unsigned long x)
+{
+ unsigned long c;
+ x &= 0xFFFFFFFF;
+ c = 0;
+ while (x) {
+ ++c;
+ x >>= 1;
+ }
+ return c;
+}
+
+
+/**
+ Gets length of DER encoding of Object Identifier
+ @param nwords The number of OID words
+ @param words The actual OID words to get the size of
+ @param outlen [out] The length of the DER encoding for the given string
+ @return CRYPT_OK if successful
+*/
+int der_length_object_identifier(unsigned long *words, unsigned long nwords, unsigned long *outlen)
+{
+ unsigned long y, z, t, wordbuf;
+
+ LTC_ARGCHK(words != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+
+ /* must be >= 2 words */
+ if (nwords < 2) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* word1 = 0,1,2,3 and word2 0..39 */
+ if (words[0] > 3 || (words[0] < 2 && words[1] > 39)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* leading word is the first two */
+ z = 0;
+ wordbuf = words[0] * 40 + words[1];
+ for (y = 1; y < nwords; y++) {
+ t = der_object_identifier_bits(wordbuf);
+ z += t/7 + ((t%7) ? 1 : 0) + (wordbuf == 0 ? 1 : 0);
+ if (y < nwords - 1) {
+ /* grab next word */
+ wordbuf = words[y+1];
+ }
+ }
+
+ /* now depending on the length our length encoding changes */
+ if (z < 128) {
+ z += 2;
+ } else if (z < 256) {
+ z += 3;
+ } else if (z < 65536UL) {
+ z += 4;
+ } else {
+ return CRYPT_INVALID_ARG;
+ }
+
+ *outlen = z;
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/object_identifier/der_length_object_identifier.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/octet/der_decode_octet_string.c b/crypto/userspace/libtomcrypt/pk/asn1/der/octet/der_decode_octet_string.c
new file mode 100644
index 0000000..ab5bc10
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/octet/der_decode_octet_string.c
@@ -0,0 +1,91 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_decode_octet_string.c
+ ASN.1 DER, encode a OCTET STRING, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Store a OCTET STRING
+ @param in The DER encoded OCTET STRING
+ @param inlen The size of the DER OCTET STRING
+ @param out [out] The array of octets stored (one per char)
+ @param outlen [in/out] The number of octets stored
+ @return CRYPT_OK if successful
+*/
+int der_decode_octet_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long x, y, len;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* must have header at least */
+ if (inlen < 2) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* check for 0x04 */
+ if ((in[0] & 0x1F) != 0x04) {
+ return CRYPT_INVALID_PACKET;
+ }
+ x = 1;
+
+ /* decode the length */
+ if (in[x] & 0x80) {
+ /* valid # of bytes in length are 1,2,3 */
+ y = in[x] & 0x7F;
+ if ((y == 0) || (y > 3) || ((x + y) > inlen)) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* read the length in */
+ len = 0;
+ ++x;
+ while (y--) {
+ len = (len << 8) | in[x++];
+ }
+ } else {
+ len = in[x++] & 0x7F;
+ }
+
+ /* is it too long? */
+ if (len > *outlen) {
+ *outlen = len;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ if (len + x > inlen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* read the data */
+ for (y = 0; y < len; y++) {
+ out[y] = in[x++];
+ }
+
+ *outlen = y;
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/octet/der_decode_octet_string.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/octet/der_encode_octet_string.c b/crypto/userspace/libtomcrypt/pk/asn1/der/octet/der_encode_octet_string.c
new file mode 100644
index 0000000..64a0770
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/octet/der_encode_octet_string.c
@@ -0,0 +1,86 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_encode_octet_string.c
+ ASN.1 DER, encode a OCTET STRING, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Store an OCTET STRING
+ @param in The array of OCTETS to store (one per char)
+ @param inlen The number of OCTETS to store
+ @param out [out] The destination for the DER encoded OCTET STRING
+ @param outlen [in/out] The max size and resulting size of the DER OCTET STRING
+ @return CRYPT_OK if successful
+*/
+int der_encode_octet_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long x, y, len;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* get the size */
+ if ((err = der_length_octet_string(inlen, &len)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* too big? */
+ if (len > *outlen) {
+ *outlen = len;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* encode the header+len */
+ x = 0;
+ out[x++] = 0x04;
+ if (inlen < 128) {
+ out[x++] = (unsigned char)inlen;
+ } else if (inlen < 256) {
+ out[x++] = 0x81;
+ out[x++] = (unsigned char)inlen;
+ } else if (inlen < 65536UL) {
+ out[x++] = 0x82;
+ out[x++] = (unsigned char)((inlen>>8)&255);
+ out[x++] = (unsigned char)(inlen&255);
+ } else if (inlen < 16777216UL) {
+ out[x++] = 0x83;
+ out[x++] = (unsigned char)((inlen>>16)&255);
+ out[x++] = (unsigned char)((inlen>>8)&255);
+ out[x++] = (unsigned char)(inlen&255);
+ } else {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* store octets */
+ for (y = 0; y < inlen; y++) {
+ out[x++] = in[y];
+ }
+
+ /* retun length */
+ *outlen = x;
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/octet/der_encode_octet_string.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/octet/der_length_octet_string.c b/crypto/userspace/libtomcrypt/pk/asn1/der/octet/der_length_octet_string.c
new file mode 100644
index 0000000..c494159
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/octet/der_length_octet_string.c
@@ -0,0 +1,53 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_length_octet_string.c
+ ASN.1 DER, get length of OCTET STRING, Tom St Denis
+*/
+
+#ifdef LTC_DER
+/**
+ Gets length of DER encoding of OCTET STRING
+ @param noctets The number of octets in the string to encode
+ @param outlen [out] The length of the DER encoding for the given string
+ @return CRYPT_OK if successful
+*/
+int der_length_octet_string(unsigned long noctets, unsigned long *outlen)
+{
+ LTC_ARGCHK(outlen != NULL);
+
+ if (noctets < 128) {
+ /* 04 LL DD DD DD ... */
+ *outlen = 2 + noctets;
+ } else if (noctets < 256) {
+ /* 04 81 LL DD DD DD ... */
+ *outlen = 3 + noctets;
+ } else if (noctets < 65536UL) {
+ /* 04 82 LL LL DD DD DD ... */
+ *outlen = 4 + noctets;
+ } else if (noctets < 16777216UL) {
+ /* 04 83 LL LL LL DD DD DD ... */
+ *outlen = 5 + noctets;
+ } else {
+ return CRYPT_INVALID_ARG;
+ }
+
+ return CRYPT_OK;
+}
+
+#endif
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/octet/der_length_octet_string.c,v $ */
+/* $Revision: 1.3 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/printable_string/der_decode_printable_string.c b/crypto/userspace/libtomcrypt/pk/asn1/der/printable_string/der_decode_printable_string.c
new file mode 100644
index 0000000..8504f77
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/printable_string/der_decode_printable_string.c
@@ -0,0 +1,96 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_decode_printable_string.c
+ ASN.1 DER, encode a printable STRING, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Store a printable STRING
+ @param in The DER encoded printable STRING
+ @param inlen The size of the DER printable STRING
+ @param out [out] The array of octets stored (one per char)
+ @param outlen [in/out] The number of octets stored
+ @return CRYPT_OK if successful
+*/
+int der_decode_printable_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long x, y, len;
+ int t;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* must have header at least */
+ if (inlen < 2) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* check for 0x13 */
+ if ((in[0] & 0x1F) != 0x13) {
+ return CRYPT_INVALID_PACKET;
+ }
+ x = 1;
+
+ /* decode the length */
+ if (in[x] & 0x80) {
+ /* valid # of bytes in length are 1,2,3 */
+ y = in[x] & 0x7F;
+ if ((y == 0) || (y > 3) || ((x + y) > inlen)) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* read the length in */
+ len = 0;
+ ++x;
+ while (y--) {
+ len = (len << 8) | in[x++];
+ }
+ } else {
+ len = in[x++] & 0x7F;
+ }
+
+ /* is it too long? */
+ if (len > *outlen) {
+ *outlen = len;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ if (len + x > inlen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* read the data */
+ for (y = 0; y < len; y++) {
+ t = der_printable_value_decode(in[x++]);
+ if (t == -1) {
+ return CRYPT_INVALID_ARG;
+ }
+ out[y] = t;
+ }
+
+ *outlen = y;
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/printable_string/der_decode_printable_string.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/printable_string/der_encode_printable_string.c b/crypto/userspace/libtomcrypt/pk/asn1/der/printable_string/der_encode_printable_string.c
new file mode 100644
index 0000000..deccdee
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/printable_string/der_encode_printable_string.c
@@ -0,0 +1,85 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_encode_printable_string.c
+ ASN.1 DER, encode a printable STRING, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/**
+ Store an printable STRING
+ @param in The array of printable to store (one per char)
+ @param inlen The number of printable to store
+ @param out [out] The destination for the DER encoded printable STRING
+ @param outlen [in/out] The max size and resulting size of the DER printable STRING
+ @return CRYPT_OK if successful
+*/
+int der_encode_printable_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long x, y, len;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* get the size */
+ if ((err = der_length_printable_string(in, inlen, &len)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* too big? */
+ if (len > *outlen) {
+ *outlen = len;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* encode the header+len */
+ x = 0;
+ out[x++] = 0x13;
+ if (inlen < 128) {
+ out[x++] = (unsigned char)inlen;
+ } else if (inlen < 256) {
+ out[x++] = 0x81;
+ out[x++] = (unsigned char)inlen;
+ } else if (inlen < 65536UL) {
+ out[x++] = 0x82;
+ out[x++] = (unsigned char)((inlen>>8)&255);
+ out[x++] = (unsigned char)(inlen&255);
+ } else if (inlen < 16777216UL) {
+ out[x++] = 0x83;
+ out[x++] = (unsigned char)((inlen>>16)&255);
+ out[x++] = (unsigned char)((inlen>>8)&255);
+ out[x++] = (unsigned char)(inlen&255);
+ } else {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* store octets */
+ for (y = 0; y < inlen; y++) {
+ out[x++] = der_printable_char_encode(in[y]);
+ }
+
+ /* retun length */
+ *outlen = x;
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/printable_string/der_encode_printable_string.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/printable_string/der_length_printable_string.c b/crypto/userspace/libtomcrypt/pk/asn1/der/printable_string/der_length_printable_string.c
new file mode 100644
index 0000000..997d3b5
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/printable_string/der_length_printable_string.c
@@ -0,0 +1,166 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_length_printable_string.c
+ ASN.1 DER, get length of Printable STRING, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+static const struct {
+ int code, value;
+} printable_table[] = {
+{ ' ', 32 },
+{ '\'', 39 },
+{ '(', 40 },
+{ ')', 41 },
+{ '+', 43 },
+{ ',', 44 },
+{ '-', 45 },
+{ '.', 46 },
+{ '/', 47 },
+{ '0', 48 },
+{ '1', 49 },
+{ '2', 50 },
+{ '3', 51 },
+{ '4', 52 },
+{ '5', 53 },
+{ '6', 54 },
+{ '7', 55 },
+{ '8', 56 },
+{ '9', 57 },
+{ ':', 58 },
+{ '=', 61 },
+{ '?', 63 },
+{ 'A', 65 },
+{ 'B', 66 },
+{ 'C', 67 },
+{ 'D', 68 },
+{ 'E', 69 },
+{ 'F', 70 },
+{ 'G', 71 },
+{ 'H', 72 },
+{ 'I', 73 },
+{ 'J', 74 },
+{ 'K', 75 },
+{ 'L', 76 },
+{ 'M', 77 },
+{ 'N', 78 },
+{ 'O', 79 },
+{ 'P', 80 },
+{ 'Q', 81 },
+{ 'R', 82 },
+{ 'S', 83 },
+{ 'T', 84 },
+{ 'U', 85 },
+{ 'V', 86 },
+{ 'W', 87 },
+{ 'X', 88 },
+{ 'Y', 89 },
+{ 'Z', 90 },
+{ 'a', 97 },
+{ 'b', 98 },
+{ 'c', 99 },
+{ 'd', 100 },
+{ 'e', 101 },
+{ 'f', 102 },
+{ 'g', 103 },
+{ 'h', 104 },
+{ 'i', 105 },
+{ 'j', 106 },
+{ 'k', 107 },
+{ 'l', 108 },
+{ 'm', 109 },
+{ 'n', 110 },
+{ 'o', 111 },
+{ 'p', 112 },
+{ 'q', 113 },
+{ 'r', 114 },
+{ 's', 115 },
+{ 't', 116 },
+{ 'u', 117 },
+{ 'v', 118 },
+{ 'w', 119 },
+{ 'x', 120 },
+{ 'y', 121 },
+{ 'z', 122 },
+};
+
+int der_printable_char_encode(int c)
+{
+ int x;
+ for (x = 0; x < (int)(sizeof(printable_table)/sizeof(printable_table[0])); x++) {
+ if (printable_table[x].code == c) {
+ return printable_table[x].value;
+ }
+ }
+ return -1;
+}
+
+int der_printable_value_decode(int v)
+{
+ int x;
+ for (x = 0; x < (int)(sizeof(printable_table)/sizeof(printable_table[0])); x++) {
+ if (printable_table[x].value == v) {
+ return printable_table[x].code;
+ }
+ }
+ return -1;
+}
+
+/**
+ Gets length of DER encoding of Printable STRING
+ @param octets The values you want to encode
+ @param noctets The number of octets in the string to encode
+ @param outlen [out] The length of the DER encoding for the given string
+ @return CRYPT_OK if successful
+*/
+int der_length_printable_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen)
+{
+ unsigned long x;
+
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(octets != NULL);
+
+ /* scan string for validity */
+ for (x = 0; x < noctets; x++) {
+ if (der_printable_char_encode(octets[x]) == -1) {
+ return CRYPT_INVALID_ARG;
+ }
+ }
+
+ if (noctets < 128) {
+ /* 16 LL DD DD DD ... */
+ *outlen = 2 + noctets;
+ } else if (noctets < 256) {
+ /* 16 81 LL DD DD DD ... */
+ *outlen = 3 + noctets;
+ } else if (noctets < 65536UL) {
+ /* 16 82 LL LL DD DD DD ... */
+ *outlen = 4 + noctets;
+ } else if (noctets < 16777216UL) {
+ /* 16 83 LL LL LL DD DD DD ... */
+ *outlen = 5 + noctets;
+ } else {
+ return CRYPT_INVALID_ARG;
+ }
+
+ return CRYPT_OK;
+}
+
+#endif
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/printable_string/der_length_printable_string.c,v $ */
+/* $Revision: 1.3 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_ex.c b/crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_ex.c
new file mode 100644
index 0000000..2067437
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_ex.c
@@ -0,0 +1,287 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include <stdarg.h>
+
+
+/**
+ @file der_decode_sequence_ex.c
+ ASN.1 DER, decode a SEQUENCE, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/**
+ Decode a SEQUENCE
+ @param in The DER encoded input
+ @param inlen The size of the input
+ @param list The list of items to decode
+ @param outlen The number of items in the list
+ @param ordered Search an unordeded or ordered list
+ @return CRYPT_OK on success
+*/
+int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen,
+ ltc_asn1_list *list, unsigned long outlen, int ordered)
+{
+ int err, type;
+ unsigned long size, x, y, z, i, blksize;
+ void *data;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(list != NULL);
+
+ /* get blk size */
+ if (inlen < 2) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* sequence type? We allow 0x30 SEQUENCE and 0x31 SET since fundamentally they're the same structure */
+ x = 0;
+ if (in[x] != 0x30 && in[x] != 0x31) {
+ return CRYPT_INVALID_PACKET;
+ }
+ ++x;
+
+ if (in[x] < 128) {
+ blksize = in[x++];
+ } else if (in[x] & 0x80) {
+ if (in[x] < 0x81 || in[x] > 0x83) {
+ return CRYPT_INVALID_PACKET;
+ }
+ y = in[x++] & 0x7F;
+
+ /* would reading the len bytes overrun? */
+ if (x + y > inlen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* read len */
+ blksize = 0;
+ while (y--) {
+ blksize = (blksize << 8) | (unsigned long)in[x++];
+ }
+ }
+
+ /* would this blksize overflow? */
+ if (x + blksize > inlen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* mark all as unused */
+ for (i = 0; i < outlen; i++) {
+ list[i].used = 0;
+ }
+
+ /* ok read data */
+ inlen = blksize;
+ for (i = 0; i < outlen; i++) {
+ z = 0;
+ type = list[i].type;
+ size = list[i].size;
+ data = list[i].data;
+ if (!ordered && list[i].used == 1) { continue; }
+
+ if (type == LTC_ASN1_EOL) {
+ break;
+ }
+
+ switch (type) {
+ case LTC_ASN1_BOOLEAN:
+ z = inlen;
+ if ((err = der_decode_boolean(in + x, z, ((int *)data))) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((err = der_length_boolean(&z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_INTEGER:
+ z = inlen;
+ if ((err = der_decode_integer(in + x, z, data)) != CRYPT_OK) {
+ if (!ordered) { continue; }
+ goto LBL_ERR;
+ }
+ if ((err = der_length_integer(data, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_SHORT_INTEGER:
+ z = inlen;
+ if ((err = der_decode_short_integer(in + x, z, data)) != CRYPT_OK) {
+ if (!ordered) { continue; }
+ goto LBL_ERR;
+ }
+ if ((err = der_length_short_integer(((unsigned long*)data)[0], &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ break;
+
+ case LTC_ASN1_BIT_STRING:
+ z = inlen;
+ if ((err = der_decode_bit_string(in + x, z, data, &size)) != CRYPT_OK) {
+ if (!ordered) { continue; }
+ goto LBL_ERR;
+ }
+ list[i].size = size;
+ if ((err = der_length_bit_string(size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_OCTET_STRING:
+ z = inlen;
+ if ((err = der_decode_octet_string(in + x, z, data, &size)) != CRYPT_OK) {
+ if (!ordered) { continue; }
+ goto LBL_ERR;
+ }
+ list[i].size = size;
+ if ((err = der_length_octet_string(size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_NULL:
+ if (inlen < 2 || in[x] != 0x05 || in[x+1] != 0x00) {
+ if (!ordered) { continue; }
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+ z = 2;
+ break;
+
+ case LTC_ASN1_OBJECT_IDENTIFIER:
+ z = inlen;
+ if ((err = der_decode_object_identifier(in + x, z, data, &size)) != CRYPT_OK) {
+ if (!ordered) { continue; }
+ goto LBL_ERR;
+ }
+ list[i].size = size;
+ if ((err = der_length_object_identifier(data, size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_IA5_STRING:
+ z = inlen;
+ if ((err = der_decode_ia5_string(in + x, z, data, &size)) != CRYPT_OK) {
+ if (!ordered) { continue; }
+ goto LBL_ERR;
+ }
+ list[i].size = size;
+ if ((err = der_length_ia5_string(data, size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+
+ case LTC_ASN1_PRINTABLE_STRING:
+ z = inlen;
+ if ((err = der_decode_printable_string(in + x, z, data, &size)) != CRYPT_OK) {
+ if (!ordered) { continue; }
+ goto LBL_ERR;
+ }
+ list[i].size = size;
+ if ((err = der_length_printable_string(data, size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_UTF8_STRING:
+ z = inlen;
+ if ((err = der_decode_utf8_string(in + x, z, data, &size)) != CRYPT_OK) {
+ if (!ordered) { continue; }
+ goto LBL_ERR;
+ }
+ list[i].size = size;
+ if ((err = der_length_utf8_string(data, size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_UTCTIME:
+ z = inlen;
+ if ((err = der_decode_utctime(in + x, &z, data)) != CRYPT_OK) {
+ if (!ordered) { continue; }
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_SET:
+ z = inlen;
+ if ((err = der_decode_set(in + x, z, data, size)) != CRYPT_OK) {
+ if (!ordered) { continue; }
+ goto LBL_ERR;
+ }
+ if ((err = der_length_sequence(data, size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_SETOF:
+ case LTC_ASN1_SEQUENCE:
+ /* detect if we have the right type */
+ if ((type == LTC_ASN1_SETOF && (in[x] & 0x3F) != 0x31) || (type == LTC_ASN1_SEQUENCE && (in[x] & 0x3F) != 0x30)) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+
+ z = inlen;
+ if ((err = der_decode_sequence(in + x, z, data, size)) != CRYPT_OK) {
+ if (!ordered) { continue; }
+ goto LBL_ERR;
+ }
+ if ((err = der_length_sequence(data, size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+
+ case LTC_ASN1_CHOICE:
+ z = inlen;
+ if ((err = der_decode_choice(in + x, &z, data, size)) != CRYPT_OK) {
+ if (!ordered) { continue; }
+ goto LBL_ERR;
+ }
+ break;
+
+ default:
+ err = CRYPT_INVALID_ARG;
+ goto LBL_ERR;
+ }
+ x += z;
+ inlen -= z;
+ list[i].used = 1;
+ if (!ordered) {
+ /* restart the decoder */
+ i = -1;
+ }
+ }
+
+ for (i = 0; i < outlen; i++) {
+ if (list[i].used == 0) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+ }
+ err = CRYPT_OK;
+
+LBL_ERR:
+ return err;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_ex.c,v $ */
+/* $Revision: 1.16 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_flexi.c b/crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_flexi.c
new file mode 100644
index 0000000..3f01a57
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_flexi.c
@@ -0,0 +1,394 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include <linux/slab.h>
+
+/**
+ @file der_decode_sequence_flexi.c
+ ASN.1 DER, decode an array of ASN.1 types with a flexi parser, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+static unsigned long fetch_length(const unsigned char *in, unsigned long inlen)
+{
+ unsigned long x, y, z;
+
+ y = 0;
+
+ /* skip type and read len */
+ if (inlen < 2) {
+ return 0xFFFFFFFF;
+ }
+ ++in; ++y;
+
+ /* read len */
+ x = *in++; ++y;
+
+ /* <128 means literal */
+ if (x < 128) {
+ return x+y;
+ }
+ x &= 0x7F; /* the lower 7 bits are the length of the length */
+ inlen -= 2;
+
+ /* len means len of len! */
+ if (x == 0 || x > 4 || x > inlen) {
+ return 0xFFFFFFFF;
+ }
+
+ y += x;
+ z = 0;
+ while (x--) {
+ z = (z<<8) | ((unsigned long)*in);
+ ++in;
+ }
+ return z+y;
+}
+
+/**
+ ASN.1 DER Flexi(ble) decoder will decode arbitrary DER packets and create a linked list of the decoded elements.
+ @param in The input buffer
+ @param inlen [in/out] The length of the input buffer and on output the amount of decoded data
+ @param out [out] A pointer to the linked list
+ @return CRYPT_OK on success.
+*/
+int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out)
+{
+ ltc_asn1_list *l;
+ unsigned long err, type, len, totlen, x, y;
+ void *realloc_tmp;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(inlen != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ l = NULL;
+ totlen = 0;
+
+ /* scan the input and and get lengths and what not */
+ while (*inlen) {
+ /* read the type byte */
+ type = *in;
+
+ /* fetch length */
+ len = fetch_length(in, *inlen);
+ if (len > *inlen) {
+ err = CRYPT_INVALID_PACKET;
+ goto error;
+ }
+
+ /* alloc new link */
+ if (l == NULL) {
+ l = XCALLOC(1, sizeof(*l));
+ if (l == NULL) {
+ err = CRYPT_MEM;
+ goto error;
+ }
+ } else {
+ l->next = XCALLOC(1, sizeof(*l));
+ if (l->next == NULL) {
+ err = CRYPT_MEM;
+ goto error;
+ }
+ l->next->prev = l;
+ l = l->next;
+ }
+
+ /* now switch on type */
+ switch (type) {
+ case 0x01: /* BOOLEAN */
+ l->type = LTC_ASN1_BOOLEAN;
+ l->size = 1;
+ l->data = XCALLOC(1, sizeof(int));
+
+ if ((err = der_decode_boolean(in, *inlen, l->data)) != CRYPT_OK) {
+ goto error;
+ }
+
+ if ((err = der_length_boolean(&len)) != CRYPT_OK) {
+ goto error;
+ }
+ break;
+
+ case 0x02: /* INTEGER */
+ /* init field */
+ l->type = LTC_ASN1_INTEGER;
+ l->size = 1;
+
+ l->data = XMALLOC(sizeof(mp_int));
+ if (l->data == NULL) {
+ err = CRYPT_MEM;
+ goto error;
+ }
+
+ if ((err = mp_init((mp_int_t)l->data)) != CRYPT_OK) {
+ goto error;
+ }
+
+ /* decode field */
+ if ((err = der_decode_integer(in, *inlen, (mp_int_t)l->data)) != CRYPT_OK) {
+ goto error;
+ }
+
+ /* calc length of object */
+ if ((err = der_length_integer((mp_int_t)l->data, &len)) != CRYPT_OK) {
+ goto error;
+ }
+ break;
+
+ case 0x03: /* BIT */
+ /* init field */
+ l->type = LTC_ASN1_BIT_STRING;
+ l->size = len * 8; /* *8 because we store decoded bits one per char and they are encoded 8 per char. */
+
+ if ((l->data = XCALLOC(1, l->size)) == NULL) {
+ err = CRYPT_MEM;
+ goto error;
+ }
+
+ if ((err = der_decode_bit_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) {
+ goto error;
+ }
+
+ if ((err = der_length_bit_string(l->size, &len)) != CRYPT_OK) {
+ goto error;
+ }
+ break;
+
+ case 0x04: /* OCTET */
+
+ /* init field */
+ l->type = LTC_ASN1_OCTET_STRING;
+ l->size = len;
+
+ if ((l->data = XCALLOC(1, l->size)) == NULL) {
+ err = CRYPT_MEM;
+ goto error;
+ }
+
+ if ((err = der_decode_octet_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) {
+ goto error;
+ }
+
+ if ((err = der_length_octet_string(l->size, &len)) != CRYPT_OK) {
+ goto error;
+ }
+ break;
+
+ case 0x05: /* NULL */
+
+ /* valid NULL is 0x05 0x00 */
+ if (in[0] != 0x05 || in[1] != 0x00) {
+ err = CRYPT_INVALID_PACKET;
+ goto error;
+ }
+
+ /* simple to store ;-) */
+ l->type = LTC_ASN1_NULL;
+ l->data = NULL;
+ l->size = 0;
+ len = 2;
+
+ break;
+
+ case 0x06: /* OID */
+
+ /* init field */
+ l->type = LTC_ASN1_OBJECT_IDENTIFIER;
+ l->size = len;
+
+ if ((l->data = XCALLOC(len, sizeof(unsigned long))) == NULL) {
+ err = CRYPT_MEM;
+ goto error;
+ }
+
+ if ((err = der_decode_object_identifier(in, *inlen, l->data, &l->size)) != CRYPT_OK) {
+ goto error;
+ }
+
+ if ((err = der_length_object_identifier(l->data, l->size, &len)) != CRYPT_OK) {
+ goto error;
+ }
+
+ /* resize it to save a bunch of mem */
+ if ((realloc_tmp = XREALLOC(l->data, l->size * sizeof(unsigned long))) == NULL) {
+ /* out of heap but this is not an error */
+ break;
+ }
+ l->data = realloc_tmp;
+ break;
+
+ case 0x0C: /* UTF8 */
+
+ /* init field */
+ l->type = LTC_ASN1_UTF8_STRING;
+ l->size = len;
+
+ if ((l->data = XCALLOC(sizeof(wchar_t), l->size)) == NULL) {
+ err = CRYPT_MEM;
+ goto error;
+ }
+
+ if ((err = der_decode_utf8_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) {
+ goto error;
+ }
+
+ if ((err = der_length_utf8_string(l->data, l->size, &len)) != CRYPT_OK) {
+ goto error;
+ }
+ break;
+
+ case 0x13: /* PRINTABLE */
+
+ /* init field */
+ l->type = LTC_ASN1_PRINTABLE_STRING;
+ l->size = len;
+
+ if ((l->data = XCALLOC(1, l->size)) == NULL) {
+ err = CRYPT_MEM;
+ goto error;
+ }
+
+ if ((err = der_decode_printable_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) {
+ goto error;
+ }
+
+ if ((err = der_length_printable_string(l->data, l->size, &len)) != CRYPT_OK) {
+ goto error;
+ }
+ break;
+
+ case 0x16: /* IA5 */
+
+ /* init field */
+ l->type = LTC_ASN1_IA5_STRING;
+ l->size = len;
+
+ if ((l->data = XCALLOC(1, l->size)) == NULL) {
+ err = CRYPT_MEM;
+ goto error;
+ }
+
+ if ((err = der_decode_ia5_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) {
+ goto error;
+ }
+
+ if ((err = der_length_ia5_string(l->data, l->size, &len)) != CRYPT_OK) {
+ goto error;
+ }
+ break;
+
+ case 0x17: /* UTC TIME */
+
+ /* init field */
+ l->type = LTC_ASN1_UTCTIME;
+ l->size = 1;
+
+ if ((l->data = XCALLOC(1, sizeof(ltc_utctime))) == NULL) {
+ err = CRYPT_MEM;
+ goto error;
+ }
+
+ len = *inlen;
+ if ((err = der_decode_utctime(in, &len, l->data)) != CRYPT_OK) {
+ goto error;
+ }
+
+ if ((err = der_length_utctime(l->data, &len)) != CRYPT_OK) {
+ goto error;
+ }
+ break;
+
+ case 0x30: /* SEQUENCE */
+ case 0x31: /* SET */
+
+ /* init field */
+ l->type = (type == 0x30) ? LTC_ASN1_SEQUENCE : LTC_ASN1_SET;
+
+ /* we have to decode the SEQUENCE header and get it's length */
+
+ /* move past type */
+ ++in; --(*inlen);
+
+ /* read length byte */
+ x = *in++; --(*inlen);
+
+ /* smallest SEQUENCE/SET header */
+ y = 2;
+
+ /* now if it's > 127 the next bytes are the length of the length */
+ if (x > 128) {
+ x &= 0x7F;
+ in += x;
+ *inlen -= x;
+
+ /* update sequence header len */
+ y += x;
+ }
+
+ /* Sequence elements go as child */
+ len = len - y;
+ if ((err = der_decode_sequence_flexi(in, &len, &(l->child))) != CRYPT_OK) {
+ goto error;
+ }
+
+ /* len update */
+ totlen += y;
+
+ /* link them up y0 */
+ l->child->parent = l;
+
+ break;
+ default:
+ /* invalid byte ... this is a soft error */
+ /* remove link */
+ l = l->prev;
+ XFREE(l->next);
+ l->next = NULL;
+ goto outside;
+ }
+
+ /* advance pointers */
+ totlen += len;
+ in += len;
+ *inlen -= len;
+ }
+
+outside:
+
+ /* rewind l please */
+ while (l->prev != NULL || l->parent != NULL) {
+ if (l->parent != NULL) {
+ l = l->parent;
+ } else {
+ l = l->prev;
+ }
+ }
+
+ /* return */
+ *out = l;
+ *inlen = totlen;
+ return CRYPT_OK;
+
+error:
+ /* free list */
+ der_sequence_free(l);
+
+ return err;
+}
+
+#endif
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_flexi.c,v $ */
+/* $Revision: 1.26 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_multi.c b/crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_multi.c
new file mode 100644
index 0000000..d1b7878
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_multi.c
@@ -0,0 +1,140 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include <stdarg.h>
+#include <linux/slab.h>
+
+
+/**
+ @file der_decode_sequence_multi.c
+ ASN.1 DER, decode a SEQUENCE, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/**
+ Decode a SEQUENCE type using a VA list
+ @param in Input buffer
+ @param inlen Length of input in octets
+ @remark <...> is of the form <type, size, data> (int, unsigned long, void*)
+ @return CRYPT_OK on success
+*/
+int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
+{
+ int err, type;
+ unsigned long size, x;
+ void *data;
+ va_list args;
+ ltc_asn1_list *list;
+
+ LTC_ARGCHK(in != NULL);
+
+ /* get size of output that will be required */
+ va_start(args, inlen);
+ x = 0;
+ for (;;) {
+ type = va_arg(args, int);
+ size = va_arg(args, unsigned long);
+ data = va_arg(args, void*);
+
+ if (type == LTC_ASN1_EOL) {
+ break;
+ }
+
+ switch (type) {
+ case LTC_ASN1_BOOLEAN:
+ case LTC_ASN1_INTEGER:
+ case LTC_ASN1_SHORT_INTEGER:
+ case LTC_ASN1_BIT_STRING:
+ case LTC_ASN1_OCTET_STRING:
+ case LTC_ASN1_NULL:
+ case LTC_ASN1_OBJECT_IDENTIFIER:
+ case LTC_ASN1_IA5_STRING:
+ case LTC_ASN1_PRINTABLE_STRING:
+ case LTC_ASN1_UTF8_STRING:
+ case LTC_ASN1_UTCTIME:
+ case LTC_ASN1_SET:
+ case LTC_ASN1_SETOF:
+ case LTC_ASN1_SEQUENCE:
+ case LTC_ASN1_CHOICE:
+ ++x;
+ break;
+
+ default:
+ va_end(args);
+ return CRYPT_INVALID_ARG;
+ }
+ }
+ va_end(args);
+
+ /* allocate structure for x elements */
+ if (x == 0) {
+ return CRYPT_NOP;
+ }
+
+ list = XCALLOC(sizeof(*list), x);
+ if (list == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* fill in the structure */
+ va_start(args, inlen);
+ x = 0;
+ for (;;) {
+ type = va_arg(args, int);
+ size = va_arg(args, unsigned long);
+ data = va_arg(args, void*);
+
+ if (type == LTC_ASN1_EOL) {
+ break;
+ }
+
+ switch (type) {
+ case LTC_ASN1_BOOLEAN:
+ case LTC_ASN1_INTEGER:
+ case LTC_ASN1_SHORT_INTEGER:
+ case LTC_ASN1_BIT_STRING:
+ case LTC_ASN1_OCTET_STRING:
+ case LTC_ASN1_NULL:
+ case LTC_ASN1_OBJECT_IDENTIFIER:
+ case LTC_ASN1_IA5_STRING:
+ case LTC_ASN1_PRINTABLE_STRING:
+ case LTC_ASN1_UTF8_STRING:
+ case LTC_ASN1_UTCTIME:
+ case LTC_ASN1_SEQUENCE:
+ case LTC_ASN1_SET:
+ case LTC_ASN1_SETOF:
+ case LTC_ASN1_CHOICE:
+ list[x].type = type;
+ list[x].size = size;
+ list[x++].data = data;
+ break;
+
+ default:
+ va_end(args);
+ err = CRYPT_INVALID_ARG;
+ goto LBL_ERR;
+ }
+ }
+ va_end(args);
+
+ err = der_decode_sequence(in, inlen, list, x);
+LBL_ERR:
+ XFREE(list);
+ return err;
+}
+
+#endif
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_multi.c,v $ */
+/* $Revision: 1.13 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_encode_sequence_ex.c b/crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_encode_sequence_ex.c
new file mode 100644
index 0000000..e92f7c3
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_encode_sequence_ex.c
@@ -0,0 +1,335 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include <stdarg.h>
+
+
+/**
+ @file der_encode_sequence_ex.c
+ ASN.1 DER, encode a SEQUENCE, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/**
+ Encode a SEQUENCE
+ @param list The list of items to encode
+ @param inlen The number of items in the list
+ @param out [out] The destination
+ @param outlen [in/out] The size of the output
+ @param type_of LTC_ASN1_SEQUENCE or LTC_ASN1_SET/LTC_ASN1_SETOF
+ @return CRYPT_OK on success
+*/
+int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen, int type_of)
+{
+ int err, type;
+ unsigned long size, x, y, z, i;
+ void *data;
+
+ LTC_ARGCHK(list != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* get size of output that will be required */
+ y = 0;
+ for (i = 0; i < inlen; i++) {
+ type = list[i].type;
+ size = list[i].size;
+ data = list[i].data;
+
+ if (type == LTC_ASN1_EOL) {
+ break;
+ }
+
+ switch (type) {
+ case LTC_ASN1_BOOLEAN:
+ if ((err = der_length_boolean(&x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_INTEGER:
+ if ((err = der_length_integer(data, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_SHORT_INTEGER:
+ if ((err = der_length_short_integer(*((unsigned long*)data), &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_BIT_STRING:
+ if ((err = der_length_bit_string(size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_OCTET_STRING:
+ if ((err = der_length_octet_string(size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_NULL:
+ y += 2;
+ break;
+
+ case LTC_ASN1_OBJECT_IDENTIFIER:
+ if ((err = der_length_object_identifier(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_IA5_STRING:
+ if ((err = der_length_ia5_string(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_PRINTABLE_STRING:
+ if ((err = der_length_printable_string(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_UTF8_STRING:
+ if ((err = der_length_utf8_string(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_UTCTIME:
+ if ((err = der_length_utctime(data, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_SET:
+ case LTC_ASN1_SETOF:
+ case LTC_ASN1_SEQUENCE:
+ if ((err = der_length_sequence(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ default:
+ err = CRYPT_INVALID_ARG;
+ goto LBL_ERR;
+ }
+ }
+
+ /* calc header size */
+ z = y;
+ if (y < 128) {
+ y += 2;
+ } else if (y < 256) {
+ /* 0x30 0x81 LL */
+ y += 3;
+ } else if (y < 65536UL) {
+ /* 0x30 0x82 LL LL */
+ y += 4;
+ } else if (y < 16777216UL) {
+ /* 0x30 0x83 LL LL LL */
+ y += 5;
+ } else {
+ err = CRYPT_INVALID_ARG;
+ goto LBL_ERR;
+ }
+
+ /* too big ? */
+ if (*outlen < y) {
+ *outlen = y;
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto LBL_ERR;
+ }
+
+ /* store header */
+ x = 0;
+ out[x++] = (type_of == LTC_ASN1_SEQUENCE) ? 0x30 : 0x31;
+
+ if (z < 128) {
+ out[x++] = (unsigned char)z;
+ } else if (z < 256) {
+ out[x++] = 0x81;
+ out[x++] = (unsigned char)z;
+ } else if (z < 65536UL) {
+ out[x++] = 0x82;
+ out[x++] = (unsigned char)((z>>8UL)&255);
+ out[x++] = (unsigned char)(z&255);
+ } else if (z < 16777216UL) {
+ out[x++] = 0x83;
+ out[x++] = (unsigned char)((z>>16UL)&255);
+ out[x++] = (unsigned char)((z>>8UL)&255);
+ out[x++] = (unsigned char)(z&255);
+ }
+
+ /* store data */
+ *outlen -= x;
+ for (i = 0; i < inlen; i++) {
+ type = list[i].type;
+ size = list[i].size;
+ data = list[i].data;
+
+ if (type == LTC_ASN1_EOL) {
+ break;
+ }
+
+ switch (type) {
+ case LTC_ASN1_BOOLEAN:
+ z = *outlen;
+ if ((err = der_encode_boolean(*((int *)data), out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += z;
+ *outlen -= z;
+ break;
+
+ case LTC_ASN1_INTEGER:
+ z = *outlen;
+ if ((err = der_encode_integer(data, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += z;
+ *outlen -= z;
+ break;
+
+ case LTC_ASN1_SHORT_INTEGER:
+ z = *outlen;
+ if ((err = der_encode_short_integer(*((unsigned long*)data), out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += z;
+ *outlen -= z;
+ break;
+
+ case LTC_ASN1_BIT_STRING:
+ z = *outlen;
+ if ((err = der_encode_bit_string(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += z;
+ *outlen -= z;
+ break;
+
+ case LTC_ASN1_OCTET_STRING:
+ z = *outlen;
+ if ((err = der_encode_octet_string(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += z;
+ *outlen -= z;
+ break;
+
+ case LTC_ASN1_NULL:
+ out[x++] = 0x05;
+ out[x++] = 0x00;
+ *outlen -= 2;
+ break;
+
+ case LTC_ASN1_OBJECT_IDENTIFIER:
+ z = *outlen;
+ if ((err = der_encode_object_identifier(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += z;
+ *outlen -= z;
+ break;
+
+ case LTC_ASN1_IA5_STRING:
+ z = *outlen;
+ if ((err = der_encode_ia5_string(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += z;
+ *outlen -= z;
+ break;
+
+ case LTC_ASN1_PRINTABLE_STRING:
+ z = *outlen;
+ if ((err = der_encode_printable_string(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += z;
+ *outlen -= z;
+ break;
+
+ case LTC_ASN1_UTF8_STRING:
+ z = *outlen;
+ if ((err = der_encode_utf8_string(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += z;
+ *outlen -= z;
+ break;
+
+ case LTC_ASN1_UTCTIME:
+ z = *outlen;
+ if ((err = der_encode_utctime(data, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += z;
+ *outlen -= z;
+ break;
+
+ case LTC_ASN1_SET:
+ z = *outlen;
+ if ((err = der_encode_set(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += z;
+ *outlen -= z;
+ break;
+
+ case LTC_ASN1_SETOF:
+ z = *outlen;
+ if ((err = der_encode_setof(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += z;
+ *outlen -= z;
+ break;
+
+ case LTC_ASN1_SEQUENCE:
+ z = *outlen;
+ if ((err = der_encode_sequence_ex(data, size, out + x, &z, type)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += z;
+ *outlen -= z;
+ break;
+
+ default:
+ err = CRYPT_INVALID_ARG;
+ goto LBL_ERR;
+ }
+ }
+ *outlen = x;
+ err = CRYPT_OK;
+
+LBL_ERR:
+ return err;
+}
+
+#endif
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_encode_sequence_multi.c b/crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_encode_sequence_multi.c
new file mode 100644
index 0000000..7e813172
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_encode_sequence_multi.c
@@ -0,0 +1,139 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include <stdarg.h>
+#include <linux/slab.h>
+
+
+/**
+ @file der_encode_sequence_multi.c
+ ASN.1 DER, encode a SEQUENCE, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/**
+ Encode a SEQUENCE type using a VA list
+ @param out [out] Destination for data
+ @param outlen [in/out] Length of buffer and resulting length of output
+ @remark <...> is of the form <type, size, data> (int, unsigned long, void*)
+ @return CRYPT_OK on success
+*/
+int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...)
+{
+ int err, type;
+ unsigned long size, x;
+ void *data;
+ va_list args;
+ ltc_asn1_list *list;
+
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* get size of output that will be required */
+ va_start(args, outlen);
+ x = 0;
+ for (;;) {
+ type = va_arg(args, int);
+ size = va_arg(args, unsigned long);
+ data = va_arg(args, void*);
+
+ if (type == LTC_ASN1_EOL) {
+ break;
+ }
+
+ switch (type) {
+ case LTC_ASN1_BOOLEAN:
+ case LTC_ASN1_INTEGER:
+ case LTC_ASN1_SHORT_INTEGER:
+ case LTC_ASN1_BIT_STRING:
+ case LTC_ASN1_OCTET_STRING:
+ case LTC_ASN1_NULL:
+ case LTC_ASN1_OBJECT_IDENTIFIER:
+ case LTC_ASN1_IA5_STRING:
+ case LTC_ASN1_PRINTABLE_STRING:
+ case LTC_ASN1_UTF8_STRING:
+ case LTC_ASN1_UTCTIME:
+ case LTC_ASN1_SEQUENCE:
+ case LTC_ASN1_SET:
+ case LTC_ASN1_SETOF:
+ ++x;
+ break;
+
+ default:
+ va_end(args);
+ return CRYPT_INVALID_ARG;
+ }
+ }
+ va_end(args);
+
+ /* allocate structure for x elements */
+ if (x == 0) {
+ return CRYPT_NOP;
+ }
+
+ list = XCALLOC(sizeof(*list), x);
+ if (list == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* fill in the structure */
+ va_start(args, outlen);
+ x = 0;
+ for (;;) {
+ type = va_arg(args, int);
+ size = va_arg(args, unsigned long);
+ data = va_arg(args, void*);
+
+ if (type == LTC_ASN1_EOL) {
+ break;
+ }
+
+ switch (type) {
+ case LTC_ASN1_BOOLEAN:
+ case LTC_ASN1_INTEGER:
+ case LTC_ASN1_SHORT_INTEGER:
+ case LTC_ASN1_BIT_STRING:
+ case LTC_ASN1_OCTET_STRING:
+ case LTC_ASN1_NULL:
+ case LTC_ASN1_OBJECT_IDENTIFIER:
+ case LTC_ASN1_IA5_STRING:
+ case LTC_ASN1_PRINTABLE_STRING:
+ case LTC_ASN1_UTF8_STRING:
+ case LTC_ASN1_UTCTIME:
+ case LTC_ASN1_SEQUENCE:
+ case LTC_ASN1_SET:
+ case LTC_ASN1_SETOF:
+ list[x].type = type;
+ list[x].size = size;
+ list[x++].data = data;
+ break;
+
+ default:
+ va_end(args);
+ err = CRYPT_INVALID_ARG;
+ goto LBL_ERR;
+ }
+ }
+ va_end(args);
+
+ err = der_encode_sequence(list, x, out, outlen);
+LBL_ERR:
+ XFREE(list);
+ return err;
+}
+
+#endif
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_multi.c,v $ */
+/* $Revision: 1.12 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_length_sequence.c b/crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_length_sequence.c
new file mode 100644
index 0000000..d2e9803
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_length_sequence.c
@@ -0,0 +1,169 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_length_sequence.c
+ ASN.1 DER, length a SEQUENCE, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/**
+ Get the length of a DER sequence
+ @param list The sequences of items in the SEQUENCE
+ @param inlen The number of items
+ @param outlen [out] The length required in octets to store it
+ @return CRYPT_OK on success
+*/
+int der_length_sequence(ltc_asn1_list *list, unsigned long inlen,
+ unsigned long *outlen)
+{
+ int err, type;
+ unsigned long size, x, y, z, i;
+ void *data;
+
+ LTC_ARGCHK(list != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* get size of output that will be required */
+ y = 0;
+ for (i = 0; i < inlen; i++) {
+ type = list[i].type;
+ size = list[i].size;
+ data = list[i].data;
+
+ if (type == LTC_ASN1_EOL) {
+ break;
+ }
+
+ switch (type) {
+ case LTC_ASN1_BOOLEAN:
+ if ((err = der_length_boolean(&x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_INTEGER:
+ if ((err = der_length_integer(data, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_SHORT_INTEGER:
+ if ((err = der_length_short_integer(*((unsigned long *)data), &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_BIT_STRING:
+ if ((err = der_length_bit_string(size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_OCTET_STRING:
+ if ((err = der_length_octet_string(size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_NULL:
+ y += 2;
+ break;
+
+ case LTC_ASN1_OBJECT_IDENTIFIER:
+ if ((err = der_length_object_identifier(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_IA5_STRING:
+ if ((err = der_length_ia5_string(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_PRINTABLE_STRING:
+ if ((err = der_length_printable_string(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_UTCTIME:
+ if ((err = der_length_utctime(data, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_UTF8_STRING:
+ if ((err = der_length_utf8_string(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_SET:
+ case LTC_ASN1_SETOF:
+ case LTC_ASN1_SEQUENCE:
+ if ((err = der_length_sequence(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+
+ default:
+ err = CRYPT_INVALID_ARG;
+ goto LBL_ERR;
+ }
+ }
+
+ /* calc header size */
+ z = y;
+ if (y < 128) {
+ y += 2;
+ } else if (y < 256) {
+ /* 0x30 0x81 LL */
+ y += 3;
+ } else if (y < 65536UL) {
+ /* 0x30 0x82 LL LL */
+ y += 4;
+ } else if (y < 16777216UL) {
+ /* 0x30 0x83 LL LL LL */
+ y += 5;
+ } else {
+ err = CRYPT_INVALID_ARG;
+ goto LBL_ERR;
+ }
+
+ /* store size */
+ *outlen = y;
+ err = CRYPT_OK;
+
+LBL_ERR:
+ return err;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/sequence/der_length_sequence.c,v $ */
+/* $Revision: 1.14 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_sequence_free.c b/crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_sequence_free.c
new file mode 100644
index 0000000..eed73e7
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_sequence_free.c
@@ -0,0 +1,66 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include <linux/slab.h>
+
+/**
+ @file der_sequence_free.c
+ ASN.1 DER, free's a structure allocated by der_decode_sequence_flexi(), Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/**
+ Free memory allocated by der_decode_sequence_flexi()
+ @param in The list to free
+*/
+void der_sequence_free(ltc_asn1_list *in)
+{
+ ltc_asn1_list *l;
+
+ /* walk to the start of the chain */
+ while (in->prev != NULL || in->parent != NULL) {
+ if (in->parent != NULL) {
+ in = in->parent;
+ } else {
+ in = in->prev;
+ }
+ }
+
+ /* now walk the list and free stuff */
+ while (in != NULL) {
+ /* is there a child? */
+ if (in->child) {
+ /* disconnect */
+ in->child->parent = NULL;
+ der_sequence_free(in->child);
+ }
+
+ switch (in->type) {
+ case LTC_ASN1_SET:
+ case LTC_ASN1_SETOF:
+ case LTC_ASN1_SEQUENCE: break;
+ case LTC_ASN1_INTEGER : if (in->data != NULL) { mp_clear(in->data); XFREE(in->data); } break;
+ default : if (in->data != NULL) { XFREE(in->data); }
+ }
+
+ /* move to next and free current */
+ l = in->next;
+ XFREE(in);
+ in = l;
+ }
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/sequence/der_sequence_free.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/set/der_encode_set.c b/crypto/userspace/libtomcrypt/pk/asn1/der/set/der_encode_set.c
new file mode 100644
index 0000000..babb9ea
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/set/der_encode_set.c
@@ -0,0 +1,104 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include <linux/slab.h>
+
+/**
+ @file der_encode_set.c
+ ASN.1 DER, Encode a SET, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/* LTC define to ASN.1 TAG */
+static int ltc_to_asn1(int v)
+{
+ switch (v) {
+ case LTC_ASN1_BOOLEAN: return 0x01;
+ case LTC_ASN1_INTEGER:
+ case LTC_ASN1_SHORT_INTEGER: return 0x02;
+ case LTC_ASN1_BIT_STRING: return 0x03;
+ case LTC_ASN1_OCTET_STRING: return 0x04;
+ case LTC_ASN1_NULL: return 0x05;
+ case LTC_ASN1_OBJECT_IDENTIFIER: return 0x06;
+ case LTC_ASN1_UTF8_STRING: return 0x0C;
+ case LTC_ASN1_PRINTABLE_STRING: return 0x13;
+ case LTC_ASN1_IA5_STRING: return 0x16;
+ case LTC_ASN1_UTCTIME: return 0x17;
+ case LTC_ASN1_SEQUENCE: return 0x30;
+ case LTC_ASN1_SET:
+ case LTC_ASN1_SETOF: return 0x31;
+ default: return -1;
+ }
+}
+
+
+static int qsort_helper(const void *a, const void *b)
+{
+ ltc_asn1_list *A = (ltc_asn1_list *)a, *B = (ltc_asn1_list *)b;
+ int r;
+
+ r = ltc_to_asn1(A->type) - ltc_to_asn1(B->type);
+
+ /* for QSORT the order is UNDEFINED if they are "equal" which means it is NOT DETERMINISTIC. So we force it to be :-) */
+ if (r == 0) {
+ /* their order in the original list now determines the position */
+ return A->used - B->used;
+ } else {
+ return r;
+ }
+}
+
+/*
+ Encode a SET type
+ @param list The list of items to encode
+ @param inlen The number of items in the list
+ @param out [out] The destination
+ @param outlen [in/out] The size of the output
+ @return CRYPT_OK on success
+*/
+int der_encode_set(ltc_asn1_list *list, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ ltc_asn1_list *copy;
+ unsigned long x;
+ int err;
+
+ /* make copy of list */
+ copy = XCALLOC(inlen, sizeof(*copy));
+ if (copy == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* fill in used member with index so we can fully sort it */
+ for (x = 0; x < inlen; x++) {
+ copy[x] = list[x];
+ copy[x].used = x;
+ }
+
+ /* sort it by the "type" field */
+ XQSORT(copy, inlen, sizeof(*copy), &qsort_helper);
+
+ /* call der_encode_sequence_ex() */
+ err = der_encode_sequence_ex(copy, inlen, out, outlen, LTC_ASN1_SET);
+
+ /* free list */
+ XFREE(copy);
+
+ return err;
+}
+
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/set/der_encode_set.c,v $ */
+/* $Revision: 1.12 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/set/der_encode_setof.c b/crypto/userspace/libtomcrypt/pk/asn1/der/set/der_encode_setof.c
new file mode 100644
index 0000000..2a343f2
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/set/der_encode_setof.c
@@ -0,0 +1,163 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include <linux/slab.h>
+
+/**
+ @file der_encode_setof.c
+ ASN.1 DER, Encode SET OF, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+struct edge {
+ unsigned char *start;
+ unsigned long size;
+};
+
+static int qsort_helper(const void *a, const void *b)
+{
+ struct edge *A = (struct edge *)a, *B = (struct edge *)b;
+ int r;
+ unsigned long x;
+
+ /* compare min length */
+ r = XMEMCMP(A->start, B->start, MIN(A->size, B->size));
+
+ if (r == 0 && A->size != B->size) {
+ if (A->size > B->size) {
+ for (x = B->size; x < A->size; x++) {
+ if (A->start[x]) {
+ return 1;
+ }
+ }
+ } else {
+ for (x = A->size; x < B->size; x++) {
+ if (B->start[x]) {
+ return -1;
+ }
+ }
+ }
+ }
+
+ return r;
+}
+
+/**
+ Encode a SETOF stucture
+ @param list The list of items to encode
+ @param inlen The number of items in the list
+ @param out [out] The destination
+ @param outlen [in/out] The size of the output
+ @return CRYPT_OK on success
+*/
+int der_encode_setof(ltc_asn1_list *list, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long x, y, z, hdrlen;
+ int err;
+ struct edge *edges;
+ unsigned char *ptr, *buf;
+
+ /* check that they're all the same type */
+ for (x = 1; x < inlen; x++) {
+ if (list[x].type != list[x-1].type) {
+ return CRYPT_INVALID_ARG;
+ }
+ }
+
+ /* alloc buffer to store copy of output */
+ buf = XCALLOC(1, *outlen);
+ if (buf == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* encode list */
+ if ((err = der_encode_sequence_ex(list, inlen, buf, outlen, LTC_ASN1_SETOF)) != CRYPT_OK) {
+ XFREE(buf);
+ return err;
+ }
+
+ /* allocate edges */
+ edges = XCALLOC(inlen, sizeof(*edges));
+ if (edges == NULL) {
+ XFREE(buf);
+ return CRYPT_MEM;
+ }
+
+ /* skip header */
+ ptr = buf + 1;
+
+ /* now skip length data */
+ x = *ptr++;
+ if (x >= 0x80) {
+ ptr += (x & 0x7F);
+ }
+
+ /* get the size of the static header */
+ hdrlen = ((unsigned long)ptr) - ((unsigned long)buf);
+
+
+ /* scan for edges */
+ x = 0;
+ while (ptr < (buf + *outlen)) {
+ /* store start */
+ edges[x].start = ptr;
+
+ /* skip type */
+ z = 1;
+
+ /* parse length */
+ y = ptr[z++];
+ if (y < 128) {
+ edges[x].size = y;
+ } else {
+ y &= 0x7F;
+ edges[x].size = 0;
+ while (y--) {
+ edges[x].size = (edges[x].size << 8) | ((unsigned long)ptr[z++]);
+ }
+ }
+
+ /* skip content */
+ edges[x].size += z;
+ ptr += edges[x].size;
+ ++x;
+ }
+
+ /* sort based on contents (using edges) */
+ XQSORT(edges, inlen, sizeof(*edges), &qsort_helper);
+
+ /* copy static header */
+ XMEMCPY(out, buf, hdrlen);
+
+ /* copy+sort using edges+indecies to output from buffer */
+ for (y = hdrlen, x = 0; x < inlen; x++) {
+ XMEMCPY(out+y, edges[x].start, edges[x].size);
+ y += edges[x].size;
+ }
+
+#ifdef LTC_CLEAN_STACK
+ zeromem(buf, *outlen);
+#endif
+
+ /* free buffers */
+ XFREE(edges);
+ XFREE(buf);
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/set/der_encode_setof.c,v $ */
+/* $Revision: 1.12 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/short_integer/der_decode_short_integer.c b/crypto/userspace/libtomcrypt/pk/asn1/der/short_integer/der_decode_short_integer.c
new file mode 100644
index 0000000..fbb89a4
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/short_integer/der_decode_short_integer.c
@@ -0,0 +1,68 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_decode_short_integer.c
+ ASN.1 DER, decode an integer, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Read a short integer
+ @param in The DER encoded data
+ @param inlen Size of data
+ @param num [out] The integer to decode
+ @return CRYPT_OK if successful
+*/
+int der_decode_short_integer(const unsigned char *in, unsigned long inlen, unsigned long *num)
+{
+ unsigned long len, x, y;
+
+ LTC_ARGCHK(num != NULL);
+ LTC_ARGCHK(in != NULL);
+
+ /* check length */
+ if (inlen < 2) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* check header */
+ x = 0;
+ if ((in[x++] & 0x1F) != 0x02) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* get the packet len */
+ len = in[x++];
+
+ if (x + len > inlen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* read number */
+ y = 0;
+ while (len--) {
+ y = (y<<8) | (unsigned long)in[x++];
+ }
+ *num = y;
+
+ return CRYPT_OK;
+
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/short_integer/der_decode_short_integer.c,v $ */
+/* $Revision: 1.7 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/short_integer/der_encode_short_integer.c b/crypto/userspace/libtomcrypt/pk/asn1/der/short_integer/der_encode_short_integer.c
new file mode 100644
index 0000000..cd9e6d1
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/short_integer/der_encode_short_integer.c
@@ -0,0 +1,97 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_encode_short_integer.c
+ ASN.1 DER, encode an integer, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Store a short integer in the range (0,2^32-1)
+ @param num The integer to encode
+ @param out [out] The destination for the DER encoded integers
+ @param outlen [in/out] The max size and resulting size of the DER encoded integers
+ @return CRYPT_OK if successful
+*/
+int der_encode_short_integer(unsigned long num, unsigned char *out, unsigned long *outlen)
+{
+ unsigned long len, x, y, z;
+ int err;
+
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* force to 32 bits */
+ num &= 0xFFFFFFFFUL;
+
+ /* find out how big this will be */
+ if ((err = der_length_short_integer(num, &len)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (*outlen < len) {
+ *outlen = len;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* get len of output */
+ z = 0;
+ y = num;
+ while (y) {
+ ++z;
+ y >>= 8;
+ }
+
+ /* handle zero */
+ if (z == 0) {
+ z = 1;
+ }
+
+ /* see if msb is set */
+ z += (num&(1UL<<((z<<3) - 1))) ? 1 : 0;
+
+ /* adjust the number so the msB is non-zero */
+ for (x = 0; (z <= 4) && (x < (4 - z)); x++) {
+ num <<= 8;
+ }
+
+ /* store header */
+ x = 0;
+ out[x++] = 0x02;
+ out[x++] = (unsigned char)z;
+
+ /* if 31st bit is set output a leading zero and decrement count */
+ if (z == 5) {
+ out[x++] = 0;
+ --z;
+ }
+
+ /* store values */
+ for (y = 0; y < z; y++) {
+ out[x++] = (unsigned char)((num >> 24) & 0xFF);
+ num <<= 8;
+ }
+
+ /* we good */
+ *outlen = x;
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/short_integer/der_encode_short_integer.c,v $ */
+/* $Revision: 1.8 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/short_integer/der_length_short_integer.c b/crypto/userspace/libtomcrypt/pk/asn1/der/short_integer/der_length_short_integer.c
new file mode 100644
index 0000000..ec3f8f1
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/short_integer/der_length_short_integer.c
@@ -0,0 +1,70 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_length_short_integer.c
+ ASN.1 DER, get length of encoding, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+/**
+ Gets length of DER encoding of num
+ @param num The integer to get the size of
+ @param outlen [out] The length of the DER encoding for the given integer
+ @return CRYPT_OK if successful
+*/
+int der_length_short_integer(unsigned long num, unsigned long *outlen)
+{
+ unsigned long z, y, len;
+
+ LTC_ARGCHK(outlen != NULL);
+
+ /* force to 32 bits */
+ num &= 0xFFFFFFFFUL;
+
+ /* get the number of bytes */
+ z = 0;
+ y = num;
+ while (y) {
+ ++z;
+ y >>= 8;
+ }
+
+ /* handle zero */
+ if (z == 0) {
+ z = 1;
+ }
+
+ /* we need a 0x02 to indicate it's INTEGER */
+ len = 1;
+
+ /* length byte */
+ ++len;
+
+ /* bytes in value */
+ len += z;
+
+ /* see if msb is set */
+ len += (num&(1UL<<((z<<3) - 1))) ? 1 : 0;
+
+ /* return length */
+ *outlen = len;
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/short_integer/der_length_short_integer.c,v $ */
+/* $Revision: 1.6 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/utctime/der_decode_utctime.c b/crypto/userspace/libtomcrypt/pk/asn1/der/utctime/der_decode_utctime.c
new file mode 100644
index 0000000..54fc204
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/utctime/der_decode_utctime.c
@@ -0,0 +1,127 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_decode_utctime.c
+ ASN.1 DER, decode a UTCTIME, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+static int char_to_int(unsigned char x)
+{
+ switch (x) {
+ case '0': return 0;
+ case '1': return 1;
+ case '2': return 2;
+ case '3': return 3;
+ case '4': return 4;
+ case '5': return 5;
+ case '6': return 6;
+ case '7': return 7;
+ case '8': return 8;
+ case '9': return 9;
+ }
+ return 100;
+}
+
+#define DECODE_V(y, max) \
+ y = char_to_int(buf[x])*10 + char_to_int(buf[x+1]); \
+ if (y >= max) return CRYPT_INVALID_PACKET; \
+ x += 2;
+
+/**
+ Decodes a UTC time structure in DER format (reads all 6 valid encoding formats)
+ @param in Input buffer
+ @param inlen Length of input buffer in octets
+ @param out [out] Destination of UTC time structure
+ @return CRYPT_OK if successful
+*/
+int der_decode_utctime(const unsigned char *in, unsigned long *inlen,
+ ltc_utctime *out)
+{
+ unsigned char buf[32];
+ unsigned long x;
+ int y;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(inlen != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ /* check header */
+ if (*inlen < 2UL || (in[1] >= sizeof(buf)) || ((in[1] + 2UL) > *inlen)) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* decode the string */
+ for (x = 0; x < in[1]; x++) {
+ y = der_ia5_value_decode(in[x+2]);
+ if (y == -1) {
+ return CRYPT_INVALID_PACKET;
+ }
+ buf[x] = y;
+ }
+ *inlen = 2 + x;
+
+
+ /* possible encodings are
+YYMMDDhhmmZ
+YYMMDDhhmm+hh'mm'
+YYMMDDhhmm-hh'mm'
+YYMMDDhhmmssZ
+YYMMDDhhmmss+hh'mm'
+YYMMDDhhmmss-hh'mm'
+
+ So let's do a trivial decode upto [including] mm
+ */
+
+ x = 0;
+ DECODE_V(out->YY, 100);
+ DECODE_V(out->MM, 13);
+ DECODE_V(out->DD, 32);
+ DECODE_V(out->hh, 24);
+ DECODE_V(out->mm, 60);
+
+ /* clear timezone and seconds info */
+ out->off_dir = out->off_hh = out->off_mm = out->ss = 0;
+
+ /* now is it Z, +, - or 0-9 */
+ if (buf[x] == 'Z') {
+ return CRYPT_OK;
+ } else if (buf[x] == '+' || buf[x] == '-') {
+ out->off_dir = (buf[x++] == '+') ? 0 : 1;
+ DECODE_V(out->off_hh, 24);
+ DECODE_V(out->off_mm, 60);
+ return CRYPT_OK;
+ }
+
+ /* decode seconds */
+ DECODE_V(out->ss, 60);
+
+ /* now is it Z, +, - */
+ if (buf[x] == 'Z') {
+ return CRYPT_OK;
+ } else if (buf[x] == '+' || buf[x] == '-') {
+ out->off_dir = (buf[x++] == '+') ? 0 : 1;
+ DECODE_V(out->off_hh, 24);
+ DECODE_V(out->off_mm, 60);
+ return CRYPT_OK;
+ } else {
+ return CRYPT_INVALID_PACKET;
+ }
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/utctime/der_decode_utctime.c,v $ */
+/* $Revision: 1.9 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/utctime/der_encode_utctime.c b/crypto/userspace/libtomcrypt/pk/asn1/der/utctime/der_encode_utctime.c
new file mode 100644
index 0000000..cb32dfa
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/utctime/der_encode_utctime.c
@@ -0,0 +1,83 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_encode_utctime.c
+ ASN.1 DER, encode a UTCTIME, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+static const char *baseten = "0123456789";
+
+#define STORE_V(y) \
+ out[x++] = der_ia5_char_encode(baseten[(y/10) % 10]); \
+ out[x++] = der_ia5_char_encode(baseten[y % 10]);
+
+/**
+ Encodes a UTC time structure in DER format
+ @param utctime The UTC time structure to encode
+ @param out The destination of the DER encoding of the UTC time structure
+ @param outlen [in/out] The length of the DER encoding
+ @return CRYPT_OK if successful
+*/
+int der_encode_utctime(ltc_utctime *utctime,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long x, tmplen;
+ int err;
+
+ LTC_ARGCHK(utctime != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ if ((err = der_length_utctime(utctime, &tmplen)) != CRYPT_OK) {
+ return err;
+ }
+ if (tmplen > *outlen) {
+ *outlen = tmplen;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* store header */
+ out[0] = 0x17;
+
+ /* store values */
+ x = 2;
+ STORE_V(utctime->YY);
+ STORE_V(utctime->MM);
+ STORE_V(utctime->DD);
+ STORE_V(utctime->hh);
+ STORE_V(utctime->mm);
+ STORE_V(utctime->ss);
+
+ if (utctime->off_mm || utctime->off_hh) {
+ out[x++] = der_ia5_char_encode(utctime->off_dir ? '-' : '+');
+ STORE_V(utctime->off_hh);
+ STORE_V(utctime->off_mm);
+ } else {
+ out[x++] = der_ia5_char_encode('Z');
+ }
+
+ /* store length */
+ out[1] = (unsigned char)(x - 2);
+
+ /* all good let's return */
+ *outlen = x;
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/utctime/der_encode_utctime.c,v $ */
+/* $Revision: 1.10 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/utctime/der_length_utctime.c b/crypto/userspace/libtomcrypt/pk/asn1/der/utctime/der_length_utctime.c
new file mode 100644
index 0000000..e5922b0
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/utctime/der_length_utctime.c
@@ -0,0 +1,46 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_length_utctime.c
+ ASN.1 DER, get length of UTCTIME, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/**
+ Gets length of DER encoding of UTCTIME
+ @param utctime The UTC time structure to get the size of
+ @param outlen [out] The length of the DER encoding
+ @return CRYPT_OK if successful
+*/
+int der_length_utctime(ltc_utctime *utctime, unsigned long *outlen)
+{
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(utctime != NULL);
+
+ if (utctime->off_hh == 0 && utctime->off_mm == 0) {
+ /* we encode as YYMMDDhhmmssZ */
+ *outlen = 2 + 13;
+ } else {
+ /* we encode as YYMMDDhhmmss{+|-}hh'mm' */
+ *outlen = 2 + 17;
+ }
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/utctime/der_length_utctime.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/utf8/der_decode_utf8_string.c b/crypto/userspace/libtomcrypt/pk/asn1/der/utf8/der_decode_utf8_string.c
new file mode 100644
index 0000000..9df7e23
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/utf8/der_decode_utf8_string.c
@@ -0,0 +1,111 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_decode_utf8_string.c
+ ASN.1 DER, encode a UTF8 STRING, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Store a UTF8 STRING
+ @param in The DER encoded UTF8 STRING
+ @param inlen The size of the DER UTF8 STRING
+ @param out [out] The array of utf8s stored (one per char)
+ @param outlen [in/out] The number of utf8s stored
+ @return CRYPT_OK if successful
+*/
+int der_decode_utf8_string(const unsigned char *in, unsigned long inlen,
+ wchar_t *out, unsigned long *outlen)
+{
+ wchar_t tmp;
+ unsigned long x, y, z, len;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* must have header at least */
+ if (inlen < 2) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* check for 0x0C */
+ if ((in[0] & 0x1F) != 0x0C) {
+ return CRYPT_INVALID_PACKET;
+ }
+ x = 1;
+
+ /* decode the length */
+ if (in[x] & 0x80) {
+ /* valid # of bytes in length are 1,2,3 */
+ y = in[x] & 0x7F;
+ if ((y == 0) || (y > 3) || ((x + y) > inlen)) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* read the length in */
+ len = 0;
+ ++x;
+ while (y--) {
+ len = (len << 8) | in[x++];
+ }
+ } else {
+ len = in[x++] & 0x7F;
+ }
+
+ if (len + x > inlen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* proceed to decode */
+ for (y = 0; x < inlen; ) {
+ /* get first byte */
+ tmp = in[x++];
+
+ /* count number of bytes */
+ for (z = 0; (tmp & 0x80) && (z <= 4); z++, tmp = (tmp << 1) & 0xFF);
+
+ if (z > 4 || (x + (z - 1) > inlen)) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* decode, grab upper bits */
+ tmp >>= z;
+
+ /* grab remaining bytes */
+ if (z > 1) { --z; }
+ while (z-- != 0) {
+ if ((in[x] & 0xC0) != 0x80) {
+ return CRYPT_INVALID_PACKET;
+ }
+ tmp = (tmp << 6) | ((wchar_t)in[x++] & 0x3F);
+ }
+
+ if (y > *outlen) {
+ *outlen = y;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+ out[y++] = tmp;
+ }
+ *outlen = y;
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/utf8/der_decode_utf8_string.c,v $ */
+/* $Revision: 1.8 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/utf8/der_encode_utf8_string.c b/crypto/userspace/libtomcrypt/pk/asn1/der/utf8/der_encode_utf8_string.c
new file mode 100644
index 0000000..d1efb09
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/utf8/der_encode_utf8_string.c
@@ -0,0 +1,105 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_encode_utf8_string.c
+ ASN.1 DER, encode a UTF8 STRING, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Store an UTF8 STRING
+ @param in The array of UTF8 to store (one per wchar_t)
+ @param inlen The number of UTF8 to store
+ @param out [out] The destination for the DER encoded UTF8 STRING
+ @param outlen [in/out] The max size and resulting size of the DER UTF8 STRING
+ @return CRYPT_OK if successful
+*/
+int der_encode_utf8_string(const wchar_t *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long x, y, len;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* get the size */
+ for (x = len = 0; x < inlen; x++) {
+ if (in[x] < 0 || in[x] > 0x1FFFF) {
+ return CRYPT_INVALID_ARG;
+ }
+ len += der_utf8_charsize(in[x]);
+ }
+
+ if (len < 128) {
+ y = 2 + len;
+ } else if (len < 256) {
+ y = 3 + len;
+ } else if (len < 65536UL) {
+ y = 4 + len;
+ } else if (len < 16777216UL) {
+ y = 5 + len;
+ } else {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* too big? */
+ if (y > *outlen) {
+ *outlen = len;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* encode the header+len */
+ x = 0;
+ out[x++] = 0x0C;
+ if (len < 128) {
+ out[x++] = (unsigned char)len;
+ } else if (len < 256) {
+ out[x++] = 0x81;
+ out[x++] = (unsigned char)len;
+ } else if (len < 65536UL) {
+ out[x++] = 0x82;
+ out[x++] = (unsigned char)((len>>8)&255);
+ out[x++] = (unsigned char)(len&255);
+ } else if (len < 16777216UL) {
+ out[x++] = 0x83;
+ out[x++] = (unsigned char)((len>>16)&255);
+ out[x++] = (unsigned char)((len>>8)&255);
+ out[x++] = (unsigned char)(len&255);
+ } else {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* store UTF8 */
+ for (y = 0; y < inlen; y++) {
+ switch (der_utf8_charsize(in[y])) {
+ case 1: out[x++] = (unsigned char)in[y]; break;
+ case 2: out[x++] = 0xC0 | ((in[y] >> 6) & 0x1F); out[x++] = 0x80 | (in[y] & 0x3F); break;
+ case 3: out[x++] = 0xE0 | ((in[y] >> 12) & 0x0F); out[x++] = 0x80 | ((in[y] >> 6) & 0x3F); out[x++] = 0x80 | (in[y] & 0x3F); break;
+ case 4: out[x++] = 0xF0 | ((in[y] >> 18) & 0x07); out[x++] = 0x80 | ((in[y] >> 12) & 0x3F); out[x++] = 0x80 | ((in[y] >> 6) & 0x3F); out[x++] = 0x80 | (in[y] & 0x3F); break;
+ }
+ }
+
+ /* retun length */
+ *outlen = x;
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/utf8/der_encode_utf8_string.c,v $ */
+/* $Revision: 1.9 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/utf8/der_length_utf8_string.c b/crypto/userspace/libtomcrypt/pk/asn1/der/utf8/der_length_utf8_string.c
new file mode 100644
index 0000000..920bd00
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/utf8/der_length_utf8_string.c
@@ -0,0 +1,83 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_length_utf8_string.c
+ ASN.1 DER, get length of UTF8 STRING, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/** Return the size in bytes of a UTF-8 character
+ @param c The UTF-8 character to measure
+ @return The size in bytes
+*/
+unsigned long der_utf8_charsize(const wchar_t c)
+{
+ if (c <= 0x7F) {
+ return 1;
+ } else if (c <= 0x7FF) {
+ return 2;
+ } else if (c <= 0xFFFF) {
+ return 3;
+ } else {
+ return 4;
+ }
+}
+
+/**
+ Gets length of DER encoding of UTF8 STRING
+ @param in The characters to measure the length of
+ @param noctets The number of octets in the string to encode
+ @param outlen [out] The length of the DER encoding for the given string
+ @return CRYPT_OK if successful
+*/
+int der_length_utf8_string(const wchar_t *in, unsigned long noctets, unsigned long *outlen)
+{
+ unsigned long x, len;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ len = 0;
+ for (x = 0; x < noctets; x++) {
+ if (in[x] < 0 || in[x] > 0x10FFFF) {
+ return CRYPT_INVALID_ARG;
+ }
+ len += der_utf8_charsize(in[x]);
+ }
+
+ if (len < 128) {
+ /* 0C LL DD DD DD ... */
+ *outlen = 2 + len;
+ } else if (len < 256) {
+ /* 0C 81 LL DD DD DD ... */
+ *outlen = 3 + len;
+ } else if (len < 65536UL) {
+ /* 0C 82 LL LL DD DD DD ... */
+ *outlen = 4 + len;
+ } else if (len < 16777216UL) {
+ /* 0C 83 LL LL LL DD DD DD ... */
+ *outlen = 5 + len;
+ } else {
+ return CRYPT_INVALID_ARG;
+ }
+
+ return CRYPT_OK;
+}
+
+#endif
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/utf8/der_length_utf8_string.c,v $ */
+/* $Revision: 1.6 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/x509/der_decode_subject_public_key_info.c b/crypto/userspace/libtomcrypt/pk/asn1/der/x509/der_decode_subject_public_key_info.c
new file mode 100644
index 0000000..8a5005f
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/x509/der_decode_subject_public_key_info.c
@@ -0,0 +1,112 @@
+/*
+ * New driver for /dev/crypto device (aka CryptoDev)
+
+ * Copyright (c) 2010 Katholieke Universiteit Leuven
+ *
+ * Author: Nikos Mavrogiannopoulos <[email protected]>
+ *
+ * This file is part of linux cryptodev.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#include "tomcrypt.h"
+#include <linux/slab.h>
+/**
+ @file der_encode_sequence_multi.c
+ ASN.1 DER, encode a Subject Public Key structure --nmav
+*/
+
+#ifdef LTC_DER
+
+/* AlgorithmIdentifier := SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm
+ * }
+ *
+ * SubjectPublicKeyInfo := SEQUENCE {
+ * algorithm AlgorithmIdentifier,
+ * subjectPublicKey BIT STRING
+ * }
+ */
+/**
+ Encode a SEQUENCE type using a VA list
+ @param out [out] Destination for data
+ @param outlen [in/out] Length of buffer and resulting length of output
+ @remark <...> is of the form <type, size, data> (int, unsigned long, void*)
+ @return CRYPT_OK on success
+*/
+int der_decode_subject_public_key_info(const unsigned char *in, unsigned long inlen,
+ unsigned int algorithm, void* public_key, unsigned long* public_key_len,
+ unsigned long parameters_type, ltc_asn1_list* parameters, unsigned long parameters_len)
+{
+ int err, len;
+ oid_st oid;
+ unsigned char *tmpbuf;
+ unsigned long tmpoid[16];
+ ltc_asn1_list alg_id[2];
+ ltc_asn1_list subject_pubkey[2];
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(inlen != 0);
+
+ err = pk_get_oid(algorithm, &oid);
+ if (err != CRYPT_OK) {
+ return err;
+ }
+
+ /* see if the OpenSSL DER format RSA public key will work */
+ tmpbuf = XCALLOC(1, MAX_RSA_SIZE*8);
+ if (tmpbuf == NULL) {
+ err = CRYPT_MEM;
+ goto LBL_ERR;
+ }
+
+ /* this includes the internal hash ID and optional params (NULL in this case) */
+ LTC_SET_ASN1(alg_id, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, sizeof(tmpoid)/sizeof(tmpoid[0]));
+ LTC_SET_ASN1(alg_id, 1, parameters_type, parameters, parameters_len);
+
+ /* the actual format of the SSL DER key is odd, it stores a RSAPublicKey in a **BIT** string ... so we have to extract it
+ then proceed to convert bit to octet
+ */
+ LTC_SET_ASN1(subject_pubkey, 0, LTC_ASN1_SEQUENCE, alg_id, 2);
+ LTC_SET_ASN1(subject_pubkey, 1, LTC_ASN1_BIT_STRING, tmpbuf, MAX_RSA_SIZE*8);
+
+ err=der_decode_sequence(in, inlen, subject_pubkey, 2UL);
+ if (err != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ len = subject_pubkey[1].size/8;
+ if (*public_key_len > len) {
+ memcpy(public_key, subject_pubkey[1].data, len);
+ *public_key_len = len;
+ } else {
+ *public_key_len = len;
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto LBL_ERR;
+ }
+
+ err = CRYPT_OK;
+
+LBL_ERR:
+
+ XFREE(tmpbuf);
+
+ return err;
+}
+
+#endif
+
+
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/x509/der_encode_subject_public_key_info.c b/crypto/userspace/libtomcrypt/pk/asn1/der/x509/der_encode_subject_public_key_info.c
new file mode 100644
index 0000000..4c7e966
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/x509/der_encode_subject_public_key_info.c
@@ -0,0 +1,83 @@
+/*
+ * New driver for /dev/crypto device (aka CryptoDev)
+
+ * Copyright (c) 2010 Katholieke Universiteit Leuven
+ *
+ * Author: Nikos Mavrogiannopoulos <[email protected]>
+ *
+ * This file is part of linux cryptodev.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_encode_sequence_multi.c
+ ASN.1 DER, encode a Subject Public Key structure --nmav
+*/
+
+#ifdef LTC_DER
+
+/* AlgorithmIdentifier := SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm
+ * }
+ *
+ * SubjectPublicKeyInfo := SEQUENCE {
+ * algorithm AlgorithmIdentifier,
+ * subjectPublicKey BIT STRING
+ * }
+ */
+/**
+ Encode a SEQUENCE type using a VA list
+ @param out [out] Destination for data
+ @param outlen [in/out] Length of buffer and resulting length of output
+ @remark <...> is of the form <type, size, data> (int, unsigned long, void*)
+ @return CRYPT_OK on success
+*/
+int der_encode_subject_public_key_info(unsigned char *out, unsigned long *outlen,
+ unsigned int algorithm, void* public_key, unsigned long public_key_len,
+ unsigned long parameters_type, void* parameters, unsigned long parameters_len)
+{
+ int err;
+ ltc_asn1_list alg_id[2];
+ oid_st oid;
+
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ err = pk_get_oid(algorithm, &oid);
+ if (err != CRYPT_OK) {
+ return err;
+ }
+
+ alg_id[0].data = oid.OID;
+ alg_id[0].size = oid.OIDlen;
+ alg_id[0].type = LTC_ASN1_OBJECT_IDENTIFIER;
+
+ alg_id[1].data = parameters;
+ alg_id[1].size = parameters_len;
+ alg_id[1].type = parameters_type;
+
+ return der_encode_sequence_multi(out, outlen,
+ LTC_ASN1_SEQUENCE, (unsigned long)sizeof(alg_id)/sizeof(alg_id[0]), alg_id,
+ LTC_ASN1_BIT_STRING, (unsigned long)(public_key_len*8), public_key,
+ LTC_ASN1_EOL, 0UL, NULL);
+
+}
+
+#endif
+
+
diff --git a/crypto/userspace/libtomcrypt/pk/dsa/dsa_export.c b/crypto/userspace/libtomcrypt/pk/dsa/dsa_export.c
new file mode 100644
index 0000000..f2cd714
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/dsa/dsa_export.c
@@ -0,0 +1,99 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include <linux/slab.h>
+
+/**
+ @file dsa_export.c
+ DSA implementation, export key, Tom St Denis
+*/
+
+#ifdef LTC_MDSA
+
+/**
+ Export a DSA key to a binary packet
+ @param out [out] Where to store the packet
+ @param outlen [in/out] The max size and resulting size of the packet
+ @param type The type of key to export (PK_PRIVATE or PK_PUBLIC)
+ @param key The key to export
+ @return CRYPT_OK if successful
+*/
+int dsa_export(unsigned char *out, unsigned long *outlen, int type, dsa_key *key)
+{
+ unsigned long zero=0;
+ int err;
+
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* can we store the static header? */
+ if (type == PK_PRIVATE && key->type != PK_PRIVATE) {
+ return CRYPT_PK_TYPE_MISMATCH;
+ }
+
+ if (type != PK_PUBLIC && type != PK_PRIVATE) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* This encoding is different from the one in original
+ * libtomcrypt. It uses a compatible encoding with gnutls
+ * and openssl
+ */
+ if (type == PK_PRIVATE) {
+ return der_encode_sequence_multi(out, outlen,
+ LTC_ASN1_SHORT_INTEGER, 1UL, &zero,
+ LTC_ASN1_INTEGER, 1UL, &key->p,
+ LTC_ASN1_INTEGER, 1UL, &key->q,
+ LTC_ASN1_INTEGER, 1UL, &key->g,
+ LTC_ASN1_INTEGER, 1UL, &key->y,
+ LTC_ASN1_INTEGER, 1UL, &key->x,
+ LTC_ASN1_EOL, 0UL, NULL);
+ } else {
+ unsigned long tmplen = (mp_count_bits(&key->y)/8)+8;
+ unsigned char* tmp = XMALLOC(tmplen);
+ ltc_asn1_list int_list[3];
+
+ if (tmp == NULL) {
+ return CRYPT_MEM;
+ }
+
+ err = der_encode_integer(&key->y, tmp, &tmplen);
+ if (err != CRYPT_OK) {
+ goto error;
+ }
+
+ int_list[0].data = &key->p;
+ int_list[0].size = 1UL;
+ int_list[0].type = LTC_ASN1_INTEGER;
+ int_list[1].data = &key->q;
+ int_list[1].size = 1UL;
+ int_list[1].type = LTC_ASN1_INTEGER;
+ int_list[2].data = &key->g;
+ int_list[2].size = 1UL;
+ int_list[2].type = LTC_ASN1_INTEGER;
+
+ err = der_encode_subject_public_key_info(out, outlen,
+ PKA_DSA, tmp, tmplen,
+ LTC_ASN1_SEQUENCE, int_list, sizeof(int_list)/sizeof(int_list[0]));
+
+error:
+ XFREE(tmp);
+ return err;
+ }
+}
+
+#endif
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/dsa/dsa_export.c,v $ */
+/* $Revision: 1.10 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/dsa/dsa_free.c b/crypto/userspace/libtomcrypt/pk/dsa/dsa_free.c
new file mode 100644
index 0000000..37a330d
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/dsa/dsa_free.c
@@ -0,0 +1,34 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file dsa_free.c
+ DSA implementation, free a DSA key, Tom St Denis
+*/
+
+#ifdef LTC_MDSA
+
+/**
+ Free a DSA key
+ @param key The key to free from memory
+*/
+void dsa_free(dsa_key *key)
+{
+ LTC_ARGCHKVD(key != NULL);
+ mp_clear_multi(&key->g, &key->q, &key->p, &key->x, &key->y, NULL);
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/dsa/dsa_free.c,v $ */
+/* $Revision: 1.8 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/dsa/dsa_import.c b/crypto/userspace/libtomcrypt/pk/dsa/dsa_import.c
new file mode 100644
index 0000000..99001f2
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/dsa/dsa_import.c
@@ -0,0 +1,101 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include <linux/slab.h>
+
+/**
+ @file dsa_import.c
+ DSA implementation, import a DSA key, Tom St Denis
+*/
+
+#ifdef LTC_MDSA
+
+/**
+ Import a DSA key
+ @param in The binary packet to import from
+ @param inlen The length of the binary packet
+ @param key [out] Where to store the imported key
+ @return CRYPT_OK if successful, upon error this function will free all allocated memory
+*/
+int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key)
+{
+ int err;
+ unsigned long zero = 0;
+ unsigned char* tmpbuf = NULL;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* init key */
+ if (mp_init_multi(&key->p, &key->g, &key->q, &key->x, &key->y, NULL) != CRYPT_OK) {
+ return CRYPT_MEM;
+ }
+
+ /* get key type */
+ if ((err = der_decode_sequence_multi(in, inlen,
+ LTC_ASN1_SHORT_INTEGER, 1UL, &zero,
+ LTC_ASN1_INTEGER, 1UL, &key->p,
+ LTC_ASN1_INTEGER, 1UL, &key->q,
+ LTC_ASN1_INTEGER, 1UL, &key->g,
+ LTC_ASN1_INTEGER, 1UL, &key->y,
+ LTC_ASN1_INTEGER, 1UL, &key->x,
+ LTC_ASN1_EOL, 0UL, NULL)) == CRYPT_OK) {
+ key->type = PK_PRIVATE;
+ } else { /* public */
+ ltc_asn1_list params[3];
+ unsigned long tmpbuf_len = MAX_RSA_SIZE*8;
+
+ LTC_SET_ASN1(params, 0, LTC_ASN1_INTEGER, &key->p, 1UL);
+ LTC_SET_ASN1(params, 1, LTC_ASN1_INTEGER, &key->q, 1UL);
+ LTC_SET_ASN1(params, 2, LTC_ASN1_INTEGER, &key->g, 1UL);
+
+ tmpbuf = XCALLOC(1, tmpbuf_len);
+ if (tmpbuf == NULL) {
+ err = CRYPT_MEM;
+ goto LBL_ERR;
+ }
+
+ err = der_decode_subject_public_key_info(in, inlen,
+ PKA_DSA, tmpbuf, &tmpbuf_len,
+ LTC_ASN1_SEQUENCE, params, 3);
+ if (err != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ if ((err=der_decode_integer(tmpbuf, tmpbuf_len, &key->y)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ XFREE(tmpbuf);
+ key->type = PK_PUBLIC;
+ }
+
+ key->qord = mp_unsigned_bin_size(&key->q);
+
+ if (key->qord >= LTC_MDSA_MAX_GROUP || key->qord <= 15 ||
+ (unsigned long)key->qord >= mp_unsigned_bin_size(&key->p) || (mp_unsigned_bin_size(&key->p) - key->qord) >= LTC_MDSA_DELTA) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+
+ return CRYPT_OK;
+
+LBL_ERR:
+ XFREE(tmpbuf);
+ mp_clear_multi(&key->p, &key->g, &key->q, &key->x, &key->y, NULL);
+ return err;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/dsa/dsa_import.c,v $ */
+/* $Revision: 1.14 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/dsa/dsa_make_key.c b/crypto/userspace/libtomcrypt/pk/dsa/dsa_make_key.c
new file mode 100644
index 0000000..1831853
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/dsa/dsa_make_key.c
@@ -0,0 +1,125 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include <linux/slab.h>
+
+/**
+ @file dsa_make_key.c
+ DSA implementation, generate a DSA key, Tom St Denis
+*/
+
+#ifdef LTC_MDSA
+
+/**
+ Create a DSA key
+ @param group_size Size of the multiplicative group (octets)
+ @param modulus_size Size of the modulus (octets)
+ @param key [out] Where to store the created key
+ @return CRYPT_OK if successful, upon error this function will free all allocated memory
+*/
+int dsa_make_key(int group_size, int modulus_size, dsa_key *key)
+{
+ mp_int tmp, tmp2;
+ int err, res;
+ unsigned char *buf;
+
+ LTC_ARGCHK(key != NULL);
+
+ /* check size */
+ if (group_size >= LTC_MDSA_MAX_GROUP || group_size <= 15 ||
+ group_size >= modulus_size || (modulus_size - group_size) >= LTC_MDSA_DELTA) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* allocate ram */
+ buf = XMALLOC(LTC_MDSA_DELTA);
+ if (buf == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* init mp_ints */
+ if ((err = mp_init_multi(&tmp, &tmp2, &key->g, &key->q, &key->p, &key->x, &key->y, NULL)) != CRYPT_OK) {
+ XFREE(buf);
+ return err;
+ }
+
+ /* make our prime q */
+ if ((err = rand_prime(&key->q, group_size)) != CRYPT_OK) { goto error; }
+
+ /* double q */
+ if ((err = mp_add(&key->q, &key->q, &tmp)) != CRYPT_OK) { goto error; }
+
+ /* now make a random string and multply it against q */
+ get_random_bytes(buf+1, modulus_size - group_size);
+
+ /* force magnitude */
+ buf[0] |= 0xC0;
+
+ /* force even */
+ buf[modulus_size - group_size - 1] &= ~1;
+
+ if ((err = mp_read_unsigned_bin(&tmp2, buf, modulus_size - group_size)) != CRYPT_OK) { goto error; }
+ if ((err = mp_mul(&key->q, &tmp2, &key->p)) != CRYPT_OK) { goto error; }
+ if ((err = mp_add_d(&key->p, 1, &key->p)) != CRYPT_OK) { goto error; }
+
+ /* now loop until p is prime */
+ for (;;) {
+ if ((err = mp_prime_is_prime(&key->p, 8, &res)) != CRYPT_OK) { goto error; }
+ if (res == LTC_MP_YES) break;
+
+ /* add 2q to p and 2 to tmp2 */
+ if ((err = mp_add(&tmp, &key->p, &key->p)) != CRYPT_OK) { goto error; }
+ if ((err = mp_add_d(&tmp2, 2, &tmp2)) != CRYPT_OK) { goto error; }
+ }
+
+ /* now p = (q * tmp2) + 1 is prime, find a value g for which g^tmp2 != 1 */
+ mp_set(&key->g, 1);
+
+ do {
+ if ((err = mp_add_d(&key->g, 1, &key->g)) != CRYPT_OK) { goto error; }
+ if ((err = mp_exptmod(&key->g, &tmp2, &key->p, &tmp)) != CRYPT_OK) { goto error; }
+ } while (mp_cmp_d(&tmp, 1) == LTC_MP_EQ);
+
+ /* at this point tmp generates a group of order q mod p */
+ mp_exch(&tmp, &key->g);
+
+ /* so now we have our DH structure, generator g, order q, modulus p
+ Now we need a random exponent [mod q] and it's power g^x mod p
+ */
+ do {
+ get_random_bytes(buf, group_size);
+
+ if ((err = mp_read_unsigned_bin(&key->x, buf, group_size)) != CRYPT_OK) { goto error; }
+ } while (mp_cmp_d(&key->x, 1) != LTC_MP_GT);
+ if ((err = mp_exptmod(&key->g, &key->x, &key->p, &key->y)) != CRYPT_OK) { goto error; }
+
+ key->type = PK_PRIVATE;
+ key->qord = group_size;
+
+#ifdef LTC_CLEAN_STACK
+ zeromem(buf, LTC_MDSA_DELTA);
+#endif
+
+ err = CRYPT_OK;
+ goto done;
+error:
+ mp_clear_multi(&key->g, &key->q, &key->p, &key->x, &key->y, NULL);
+done:
+ mp_clear_multi(&tmp, &tmp2, NULL);
+ XFREE(buf);
+ return err;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/dsa/dsa_make_key.c,v $ */
+/* $Revision: 1.12 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/dsa/dsa_sign_hash.c b/crypto/userspace/libtomcrypt/pk/dsa/dsa_sign_hash.c
new file mode 100644
index 0000000..b48d5a5
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/dsa/dsa_sign_hash.c
@@ -0,0 +1,147 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include <linux/slab.h>
+
+/**
+ @file dsa_sign_hash.c
+ DSA implementation, sign a hash, Tom St Denis
+*/
+
+#ifdef LTC_MDSA
+
+/**
+ Sign a hash with DSA
+ @param in The hash to sign
+ @param inlen The length of the hash to sign
+ @param r The "r" integer of the signature (caller must initialize with mp_init() first)
+ @param s The "s" integer of the signature (caller must initialize with mp_init() first)
+ @param key A private DSA key
+ @return CRYPT_OK if successful
+*/
+int dsa_sign_hash_raw(const unsigned char *in, unsigned long inlen,
+ mp_int_t r, mp_int_t s,
+ dsa_key *key)
+{
+ mp_int k, kinv, tmp;
+ unsigned char *buf;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(r != NULL);
+ LTC_ARGCHK(s != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ if (key->type != PK_PRIVATE) {
+ return CRYPT_PK_NOT_PRIVATE;
+ }
+
+ /* check group order size */
+ if (key->qord >= LTC_MDSA_MAX_GROUP) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ buf = XMALLOC(LTC_MDSA_MAX_GROUP);
+ if (buf == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* Init our temps */
+ if ((err = mp_init_multi(&k, &kinv, &tmp, NULL)) != CRYPT_OK) { goto ERRBUF; }
+
+retry:
+
+ do {
+ /* gen random k */
+ get_random_bytes(buf, key->qord);
+
+ /* read k */
+ if ((err = mp_read_unsigned_bin(&k, buf, key->qord)) != CRYPT_OK) { goto error; }
+
+ /* k > 1 ? */
+ if (mp_cmp_d(&k, 1) != LTC_MP_GT) { goto retry; }
+
+ /* test gcd */
+ if ((err = mp_gcd(&k, &key->q, &tmp)) != CRYPT_OK) { goto error; }
+ } while (mp_cmp_d(&tmp, 1) != LTC_MP_EQ);
+
+ /* now find 1/k mod q */
+ if ((err = mp_invmod(&k, &key->q, &kinv)) != CRYPT_OK) { goto error; }
+
+ /* now find r = g^k mod p mod q */
+ if ((err = mp_exptmod(&key->g, &k, &key->p, r)) != CRYPT_OK) { goto error; }
+ if ((err = mp_mod(r, &key->q, r)) != CRYPT_OK) { goto error; }
+
+ if (mp_iszero(r) == LTC_MP_YES) { goto retry; }
+
+ /* now find s = (in + xr)/k mod q */
+ if ((err = mp_read_unsigned_bin(&tmp, (unsigned char *)in, inlen)) != CRYPT_OK) { goto error; }
+ if ((err = mp_mul(&key->x, r, s)) != CRYPT_OK) { goto error; }
+ if ((err = mp_add(s, &tmp, s)) != CRYPT_OK) { goto error; }
+ if ((err = mp_mulmod(s, &kinv, &key->q, s)) != CRYPT_OK) { goto error; }
+
+ if (mp_iszero(s) == LTC_MP_YES) { goto retry; }
+
+ err = CRYPT_OK;
+error:
+ mp_clear_multi(&k, &kinv, &tmp, NULL);
+ERRBUF:
+#ifdef LTC_CLEAN_STACK
+ zeromem(buf, LTC_MDSA_MAX_GROUP);
+#endif
+ XFREE(buf);
+ return err;
+}
+
+/**
+ Sign a hash with DSA
+ @param in The hash to sign
+ @param inlen The length of the hash to sign
+ @param out [out] Where to store the signature
+ @param outlen [in/out] The max size and resulting size of the signature
+ @param key A private DSA key
+ @return CRYPT_OK if successful
+*/
+int dsa_sign_hash(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ dsa_key *key)
+{
+ mp_int r, s;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ if (mp_init_multi(&r, &s, NULL) != CRYPT_OK) {
+ return CRYPT_MEM;
+ }
+
+ if ((err = dsa_sign_hash_raw(in, inlen, &r, &s, key)) != CRYPT_OK) {
+ goto error;
+ }
+
+ err = der_encode_sequence_multi(out, outlen,
+ LTC_ASN1_INTEGER, 1UL, &r,
+ LTC_ASN1_INTEGER, 1UL, &s,
+ LTC_ASN1_EOL, 0UL, NULL);
+
+error:
+ mp_clear_multi(&r, &s, NULL);
+ return err;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/dsa/dsa_sign_hash.c,v $ */
+/* $Revision: 1.14 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/dsa/dsa_verify_hash.c b/crypto/userspace/libtomcrypt/pk/dsa/dsa_verify_hash.c
new file mode 100644
index 0000000..3a82d1b
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/dsa/dsa_verify_hash.c
@@ -0,0 +1,126 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file dsa_verify_hash.c
+ DSA implementation, verify a signature, Tom St Denis
+*/
+
+
+#ifdef LTC_MDSA
+
+/**
+ Verify a DSA signature
+ @param r DSA "r" parameter
+ @param s DSA "s" parameter
+ @param hash The hash that was signed
+ @param hashlen The length of the hash that was signed
+ @param stat [out] The result of the signature verification, 1==valid, 0==invalid
+ @param key The corresponding public DH key
+ @return CRYPT_OK if successful (even if the signature is invalid)
+*/
+int dsa_verify_hash_raw( mp_int_t r, mp_int_t s,
+ const unsigned char *hash, unsigned long hashlen,
+ int *stat, dsa_key *key)
+{
+ mp_int w, v, u1, u2;
+ int err;
+
+ LTC_ARGCHK(r != NULL);
+ LTC_ARGCHK(s != NULL);
+ LTC_ARGCHK(stat != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* default to invalid signature */
+ *stat = 0;
+
+ /* init our variables */
+ if ((err = mp_init_multi(&w, &v, &u1, &u2, NULL)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* neither r or s can be null or >q*/
+ if (mp_iszero(r) == LTC_MP_YES || mp_iszero(s) == LTC_MP_YES || mp_cmp(r, &key->q) != LTC_MP_LT || mp_cmp(s, &key->q) != LTC_MP_LT) {
+ err = CRYPT_INVALID_PACKET;
+ goto error;
+ }
+
+ /* w = 1/s mod q */
+ if ((err = mp_invmod(s, &key->q, &w)) != CRYPT_OK) { goto error; }
+
+ /* u1 = m * w mod q */
+ if ((err = mp_read_unsigned_bin(&u1, (unsigned char *)hash, hashlen)) != CRYPT_OK) { goto error; }
+ if ((err = mp_mulmod(&u1, &w, &key->q, &u1)) != CRYPT_OK) { goto error; }
+
+ /* u2 = r*w mod q */
+ if ((err = mp_mulmod(r, &w, &key->q, &u2)) != CRYPT_OK) { goto error; }
+
+ /* v = g^u1 * y^u2 mod p mod q */
+ if ((err = mp_exptmod(&key->g, &u1, &key->p, &u1)) != CRYPT_OK) { goto error; }
+ if ((err = mp_exptmod(&key->y, &u2, &key->p, &u2)) != CRYPT_OK) { goto error; }
+ if ((err = mp_mulmod(&u1, &u2, &key->p, &v)) != CRYPT_OK) { goto error; }
+ if ((err = mp_mod(&v, &key->q, &v)) != CRYPT_OK) { goto error; }
+
+ /* if r = v then we're set */
+ if (mp_cmp(r, &v) == LTC_MP_EQ) {
+ *stat = 1;
+ }
+
+ err = CRYPT_OK;
+error:
+ mp_clear_multi(&w, &v, &u1, &u2, NULL);
+ return err;
+}
+
+/**
+ Verify a DSA signature
+ @param sig The signature
+ @param siglen The length of the signature (octets)
+ @param hash The hash that was signed
+ @param hashlen The length of the hash that was signed
+ @param stat [out] The result of the signature verification, 1==valid, 0==invalid
+ @param key The corresponding public DH key
+ @return CRYPT_OK if successful (even if the signature is invalid)
+*/
+int dsa_verify_hash(const unsigned char *sig, unsigned long siglen,
+ const unsigned char *hash, unsigned long hashlen,
+ int *stat, dsa_key *key)
+{
+ int err;
+ mp_int r, s;
+
+ if ((err = mp_init_multi(&r, &s, NULL)) != CRYPT_OK) {
+ return CRYPT_MEM;
+ }
+
+ /* decode the sequence */
+ if ((err = der_decode_sequence_multi(sig, siglen,
+ LTC_ASN1_INTEGER, 1UL, &r,
+ LTC_ASN1_INTEGER, 1UL, &s,
+ LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* do the op */
+ err = dsa_verify_hash_raw(&r, &s, hash, hashlen, stat, key);
+
+LBL_ERR:
+ mp_clear_multi(&r, &s, NULL);
+ return err;
+}
+
+#endif
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/dsa/dsa_verify_hash.c,v $ */
+/* $Revision: 1.15 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/dsa/dsa_verify_key.c b/crypto/userspace/libtomcrypt/pk/dsa/dsa_verify_key.c
new file mode 100644
index 0000000..71635d2
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/dsa/dsa_verify_key.c
@@ -0,0 +1,100 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file dsa_verify_key.c
+ DSA implementation, verify a key, Tom St Denis
+*/
+
+#ifdef LTC_MDSA
+
+/**
+ Verify a DSA key for validity
+ @param key The key to verify
+ @param stat [out] Result of test, 1==valid, 0==invalid
+ @return CRYPT_OK if successful
+*/
+int dsa_verify_key(dsa_key *key, int *stat)
+{
+ mp_int tmp, tmp2;
+ int res, err;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(stat != NULL);
+
+ /* default to an invalid key */
+ *stat = 0;
+
+ /* first make sure key->q and key->p are prime */
+ if ((err = mp_prime_is_prime(&key->q, 8, &res)) != CRYPT_OK) {
+ return err;
+ }
+ if (res == 0) {
+ return CRYPT_OK;
+ }
+
+ if ((err = mp_prime_is_prime(&key->p, 8, &res)) != CRYPT_OK) {
+ return err;
+ }
+ if (res == 0) {
+ return CRYPT_OK;
+ }
+
+ /* now make sure that g is not -1, 0 or 1 and <p */
+ if (mp_cmp_d(&key->g, 0) == LTC_MP_EQ || mp_cmp_d(&key->g, 1) == LTC_MP_EQ) {
+ return CRYPT_OK;
+ }
+ if ((err = mp_init_multi(&tmp, &tmp2, NULL)) != CRYPT_OK) { return err; }
+ if ((err = mp_sub_d(&key->p, 1, &tmp)) != CRYPT_OK) { goto error; }
+ if (mp_cmp(&tmp, &key->g) == LTC_MP_EQ || mp_cmp(&key->g, &key->p) != LTC_MP_LT) {
+ err = CRYPT_OK;
+ goto error;
+ }
+
+ /* 1 < y < p-1 */
+ if (!(mp_cmp_d(&key->y, 1) == LTC_MP_GT && mp_cmp(&key->y, &tmp) == LTC_MP_LT)) {
+ err = CRYPT_OK;
+ goto error;
+ }
+
+ /* now we have to make sure that g^q = 1, and that p-1/q gives 0 remainder */
+ if ((err = mp_div(&tmp, &key->q, &tmp, &tmp2)) != CRYPT_OK) { goto error; }
+ if (mp_iszero(&tmp2) != LTC_MP_YES) {
+ err = CRYPT_OK;
+ goto error;
+ }
+
+ if ((err = mp_exptmod(&key->g, &key->q, &key->p, &tmp)) != CRYPT_OK) { goto error; }
+ if (mp_cmp_d(&tmp, 1) != LTC_MP_EQ) {
+ err = CRYPT_OK;
+ goto error;
+ }
+
+ /* now we have to make sure that y^q = 1, this makes sure y \in g^x mod p */
+ if ((err = mp_exptmod(&key->y, &key->q, &key->p, &tmp)) != CRYPT_OK) { goto error; }
+ if (mp_cmp_d(&tmp, 1) != LTC_MP_EQ) {
+ err = CRYPT_OK;
+ goto error;
+ }
+
+ /* at this point we are out of tests ;-( */
+ err = CRYPT_OK;
+ *stat = 1;
+error:
+ mp_clear_multi(&tmp, &tmp2, NULL);
+ return err;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/dsa/dsa_verify_key.c,v $ */
+/* $Revision: 1.8 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_i2osp.c b/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_i2osp.c
new file mode 100644
index 0000000..70294a5
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_i2osp.c
@@ -0,0 +1,51 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file pkcs_1_i2osp.c
+ Integer to Octet I2OSP, Tom St Denis
+*/
+
+#ifdef LTC_PKCS_1
+
+/* always stores the same # of bytes, pads with leading zero bytes
+ as required
+ */
+
+/**
+ LTC_PKCS #1 Integer to binary
+ @param n The integer to store
+ @param modulus_len The length of the RSA modulus
+ @param out [out] The destination for the integer
+ @return CRYPT_OK if successful
+*/
+int pkcs_1_i2osp(void *n, unsigned long modulus_len, unsigned char *out)
+{
+ unsigned long size;
+
+ size = mp_unsigned_bin_size(n);
+
+ if (size > modulus_len) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* store it */
+ zeromem(out, modulus_len);
+ return mp_to_unsigned_bin(n, out+(modulus_len-size));
+}
+
+#endif /* LTC_PKCS_1 */
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_i2osp.c,v $ */
+/* $Revision: 1.7 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_mgf1.c b/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_mgf1.c
new file mode 100644
index 0000000..86ba218
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_mgf1.c
@@ -0,0 +1,91 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include <ncr-int.h>
+#include <linux/slab.h>
+
+/**
+ @file pkcs_1_mgf1.c
+ The Mask Generation Function (MGF1) for LTC_PKCS #1, Tom St Denis
+*/
+
+#ifdef LTC_PKCS_1
+
+/**
+ Perform LTC_PKCS #1 MGF1 (internal)
+ @param seed The seed for MGF1
+ @param seedlen The length of the seed
+ @param hash The desired hash
+ @param mask [out] The destination
+ @param masklen The length of the mask desired
+ @return CRYPT_OK if successful
+*/
+int pkcs_1_mgf1(const struct algo_properties_st *hash,
+ const unsigned char *seed, unsigned long seedlen,
+ unsigned char *mask, unsigned long masklen)
+{
+ unsigned long hLen, x;
+ ulong32 counter;
+ int err;
+ unsigned char *buf;
+
+ LTC_ARGCHK(seed != NULL);
+ LTC_ARGCHK(mask != NULL);
+
+ /* ensure valid hash */
+ if ((err = hash_is_valid(hash)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* get hash output size */
+ hLen = hash->digest_size;
+
+ /* allocate memory */
+ buf = XMALLOC(hLen);
+ if (buf == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* start counter */
+ counter = 0;
+
+ while (masklen > 0) {
+ /* handle counter */
+ STORE32H(counter, buf);
+ ++counter;
+
+ err = hash_memory_multi(hash, buf, &hLen, seed, seedlen, buf, (unsigned long) 4, NULL, 0);
+ if (err != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* store it */
+ for (x = 0; x < hLen && masklen > 0; x++, masklen--) {
+ *mask++ = buf[x];
+ }
+ }
+
+ err = CRYPT_OK;
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(buf, hLen);
+#endif
+
+ XFREE(buf);
+
+ return err;
+}
+
+#endif /* LTC_PKCS_1 */
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c,v $ */
+/* $Revision: 1.8 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_oaep_decode.c b/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_oaep_decode.c
new file mode 100644
index 0000000..717d99d
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_oaep_decode.c
@@ -0,0 +1,192 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include <ncr-int.h>
+#include <linux/slab.h>
+
+/**
+ @file pkcs_1_oaep_decode.c
+ OAEP Padding for LTC_PKCS #1, Tom St Denis
+*/
+
+#ifdef LTC_PKCS_1
+
+/**
+ LTC_PKCS #1 v2.00 OAEP decode
+ @param msg The encoded data to decode
+ @param msglen The length of the encoded data (octets)
+ @param lparam The session or system data (can be NULL)
+ @param lparamlen The length of the lparam
+ @param modulus_bitlen The bit length of the RSA modulus
+ @param hash The desired hash
+ @param out [out] Destination of decoding
+ @param outlen [in/out] The max size and resulting size of the decoding
+ @param res [out] Result of decoding, 1==valid, 0==invalid
+ @return CRYPT_OK if successful (even if invalid)
+*/
+int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen,
+ const unsigned char *lparam, unsigned long lparamlen,
+ unsigned long modulus_bitlen, const struct algo_properties_st *hash,
+ unsigned char *out, unsigned long *outlen,
+ int *res)
+{
+ unsigned char *DB, *seed, *mask;
+ unsigned long hLen, x, y, modulus_len;
+ int err;
+
+ LTC_ARGCHK(msg != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(res != NULL);
+
+ /* default to invalid packet */
+ *res = 0;
+
+ /* test valid hash */
+ if ((err = hash_is_valid(hash)) != CRYPT_OK) {
+ return err;
+ }
+
+ hLen = hash->digest_size;
+ modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);
+
+ /* test hash/message size */
+ if ((2*hLen >= (modulus_len - 2)) || (msglen != modulus_len)) {
+ return CRYPT_PK_INVALID_SIZE;
+ }
+
+ /* allocate ram for DB/mask/salt of size modulus_len */
+ DB = XMALLOC(modulus_len);
+ mask = XMALLOC(modulus_len);
+ seed = XMALLOC(hLen);
+ if (DB == NULL || mask == NULL || seed == NULL) {
+ if (DB != NULL) {
+ XFREE(DB);
+ }
+ if (mask != NULL) {
+ XFREE(mask);
+ }
+ if (seed != NULL) {
+ XFREE(seed);
+ }
+ return CRYPT_MEM;
+ }
+
+ /* ok so it's now in the form
+
+ 0x00 || maskedseed || maskedDB
+
+ 1 || hLen || modulus_len - hLen - 1
+
+ */
+
+ /* must have leading 0x00 byte */
+ if (msg[0] != 0x00) {
+ err = CRYPT_OK;
+ goto LBL_ERR;
+ }
+
+ /* now read the masked seed */
+ x = 1;
+ XMEMCPY(seed, msg + x, hLen);
+ x += hLen;
+
+ /* now read the masked DB */
+ XMEMCPY(DB, msg + x, modulus_len - hLen - 1);
+ x += modulus_len - hLen - 1;
+
+ /* compute MGF1 of maskedDB (hLen) */
+ if ((err = pkcs_1_mgf1(hash, DB, modulus_len - hLen - 1, mask, hLen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* XOR against seed */
+ for (y = 0; y < hLen; y++) {
+ seed[y] ^= mask[y];
+ }
+
+ /* compute MGF1 of seed (k - hlen - 1) */
+ if ((err = pkcs_1_mgf1(hash, seed, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* xor against DB */
+ for (y = 0; y < (modulus_len - hLen - 1); y++) {
+ DB[y] ^= mask[y];
+ }
+
+ /* now DB == lhash || PS || 0x01 || M, PS == k - mlen - 2hlen - 2 zeroes */
+
+ /* compute lhash and store it in seed [reuse temps!] */
+ x = modulus_len;
+ if (lparam != NULL) {
+ if ((err = hash_memory(hash, lparam, lparamlen, seed, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ } else {
+ /* can't pass hash_memory a NULL so use DB with zero length */
+ if ((err = hash_memory(hash, DB, 0, seed, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* compare the lhash'es */
+ if (XMEMCMP(seed, DB, hLen) != 0) {
+ err = CRYPT_OK;
+ goto LBL_ERR;
+ }
+
+ /* now zeroes before a 0x01 */
+ for (x = hLen; x < (modulus_len - hLen - 1) && DB[x] == 0x00; x++) {
+ /* step... */
+ }
+
+ /* error out if wasn't 0x01 */
+ if (x == (modulus_len - hLen - 1) || DB[x] != 0x01) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+
+ /* rest is the message (and skip 0x01) */
+ if ((modulus_len - hLen - 1 - ++x) > *outlen) {
+ *outlen = modulus_len - hLen - 1 - x;
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto LBL_ERR;
+ }
+
+ /* copy message */
+ *outlen = modulus_len - hLen - 1 - x;
+ XMEMCPY(out, DB + x, modulus_len - hLen - 1 - x);
+ x += modulus_len - hLen - 1;
+
+ /* valid packet */
+ *res = 1;
+
+ err = CRYPT_OK;
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(DB, modulus_len);
+ zeromem(seed, hLen);
+ zeromem(mask, modulus_len);
+#endif
+
+ XFREE(seed);
+ XFREE(mask);
+ XFREE(DB);
+
+ return err;
+}
+
+#endif /* LTC_PKCS_1 */
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c,v $ */
+/* $Revision: 1.13 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_oaep_encode.c b/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_oaep_encode.c
new file mode 100644
index 0000000..331516f
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_oaep_encode.c
@@ -0,0 +1,164 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include <ncr-int.h>
+#include <linux/slab.h>
+
+/**
+ @file pkcs_1_oaep_encode.c
+ OAEP Padding for LTC_PKCS #1, Tom St Denis
+*/
+
+#ifdef LTC_PKCS_1
+
+/**
+ LTC_PKCS #1 v2.00 OAEP encode
+ @param msg The data to encode
+ @param msglen The length of the data to encode (octets)
+ @param lparam A session or system parameter (can be NULL)
+ @param lparamlen The length of the lparam data
+ @param modulus_bitlen The bit length of the RSA modulus
+ @param hash The desired hash
+ @param out [out] The destination for the encoded data
+ @param outlen [in/out] The max size and resulting size of the encoded data
+ @return CRYPT_OK if successful
+*/
+int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen,
+ const unsigned char *lparam, unsigned long lparamlen,
+ unsigned long modulus_bitlen, const struct algo_properties_st *hash,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned char *DB, *seed, *mask;
+ unsigned long hLen, x, y, modulus_len;
+ int err;
+
+ LTC_ARGCHK(msg != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* test valid hash */
+ if ((err = hash_is_valid(hash)) != CRYPT_OK) {
+ return err;
+ }
+
+ hLen = hash->digest_size;
+ modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);
+
+ /* test message size */
+ if ((2*hLen >= (modulus_len - 2)) || (msglen > (modulus_len - 2*hLen - 2))) {
+ return CRYPT_PK_INVALID_SIZE;
+ }
+
+ /* allocate ram for DB/mask/salt of size modulus_len */
+ DB = XMALLOC(modulus_len);
+ mask = XMALLOC(modulus_len);
+ seed = XMALLOC(hLen);
+ if (DB == NULL || mask == NULL || seed == NULL) {
+ if (DB != NULL) {
+ XFREE(DB);
+ }
+ if (mask != NULL) {
+ XFREE(mask);
+ }
+ if (seed != NULL) {
+ XFREE(seed);
+ }
+ return CRYPT_MEM;
+ }
+
+ /* get lhash */
+ /* DB == lhash || PS || 0x01 || M, PS == k - mlen - 2hlen - 2 zeroes */
+ x = modulus_len;
+ if (lparam != NULL) {
+ if ((err = hash_memory(hash, lparam, lparamlen, DB, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ } else {
+ /* can't pass hash_memory a NULL so use DB with zero length */
+ if ((err = hash_memory(hash, DB, 0, DB, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* append PS then 0x01 (to lhash) */
+ x = hLen;
+ y = modulus_len - msglen - 2*hLen - 2;
+ XMEMSET(DB+x, 0, y);
+ x += y;
+
+ /* 0x01 byte */
+ DB[x++] = 0x01;
+
+ /* message (length = msglen) */
+ XMEMCPY(DB+x, msg, msglen);
+ x += msglen;
+
+ /* now choose a random seed */
+ get_random_bytes(seed, hLen);
+
+ /* compute MGF1 of seed (k - hlen - 1) */
+ if ((err = pkcs_1_mgf1(hash, seed, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* xor against DB */
+ for (y = 0; y < (modulus_len - hLen - 1); y++) {
+ DB[y] ^= mask[y];
+ }
+
+ /* compute MGF1 of maskedDB (hLen) */
+ if ((err = pkcs_1_mgf1(hash, DB, modulus_len - hLen - 1, mask, hLen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* XOR against seed */
+ for (y = 0; y < hLen; y++) {
+ seed[y] ^= mask[y];
+ }
+
+ /* create string of length modulus_len */
+ if (*outlen < modulus_len) {
+ *outlen = modulus_len;
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto LBL_ERR;
+ }
+
+ /* start output which is 0x00 || maskedSeed || maskedDB */
+ x = 0;
+ out[x++] = 0x00;
+ XMEMCPY(out+x, seed, hLen);
+ x += hLen;
+ XMEMCPY(out+x, DB, modulus_len - hLen - 1);
+ x += modulus_len - hLen - 1;
+
+ *outlen = x;
+
+ err = CRYPT_OK;
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(DB, modulus_len);
+ zeromem(seed, hLen);
+ zeromem(mask, modulus_len);
+#endif
+
+ XFREE(seed);
+ XFREE(mask);
+ XFREE(DB);
+
+ return err;
+}
+
+#endif /* LTC_PKCS_1 */
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_encode.c,v $ */
+/* $Revision: 1.9 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_os2ip.c b/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_os2ip.c
new file mode 100644
index 0000000..513abb6
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_os2ip.c
@@ -0,0 +1,36 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file pkcs_1_os2ip.c
+ Octet to Integer OS2IP, Tom St Denis
+*/
+#ifdef LTC_PKCS_1
+
+/**
+ Read a binary string into an mp_int
+ @param n [out] The mp_int destination
+ @param in The binary string to read
+ @param inlen The length of the binary string
+ @return CRYPT_OK if successful
+*/
+int pkcs_1_os2ip(void *n, unsigned char *in, unsigned long inlen)
+{
+ return mp_read_unsigned_bin(n, in, inlen);
+}
+
+#endif /* LTC_PKCS_1 */
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_os2ip.c,v $ */
+/* $Revision: 1.7 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_pss_decode.c b/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_pss_decode.c
new file mode 100644
index 0000000..5d44ce8
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_pss_decode.c
@@ -0,0 +1,168 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include <ncr-int.h>
+#include <linux/slab.h>
+
+/**
+ @file pkcs_1_pss_decode.c
+ LTC_PKCS #1 PSS Signature Padding, Tom St Denis
+*/
+
+#ifdef LTC_PKCS_1
+
+/**
+ LTC_PKCS #1 v2.00 PSS decode
+ @param msghash The hash to verify
+ @param msghashlen The length of the hash (octets)
+ @param sig The signature data (encoded data)
+ @param siglen The length of the signature data (octets)
+ @param saltlen The length of the salt used (octets)
+ @param hash_algo The desired hash
+ @param modulus_bitlen The bit length of the RSA modulus
+ @param res [out] The result of the comparison, 1==valid, 0==invalid
+ @return CRYPT_OK if successful (even if the comparison failed)
+*/
+int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen,
+ const unsigned char *sig, unsigned long siglen,
+ unsigned long saltlen, const struct algo_properties_st *hash_algo,
+ unsigned long modulus_bitlen, int *res)
+{
+ unsigned char *DB, *mask, *salt, *hash;
+ unsigned long x, y, hLen, modulus_len;
+ int err;
+
+ LTC_ARGCHK(msghash != NULL);
+ LTC_ARGCHK(res != NULL);
+
+ /* default to invalid */
+ *res = 0;
+
+ /* ensure hash is valid */
+ if ((err = hash_is_valid(hash_algo)) != CRYPT_OK) {
+ return err;
+ }
+
+ hLen = hash_algo->digest_size;
+ modulus_len = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0);
+
+ /* check sizes */
+ if ((saltlen > modulus_len) ||
+ (modulus_len < hLen + saltlen + 2) || (siglen != modulus_len)) {
+ return CRYPT_PK_INVALID_SIZE;
+ }
+
+ /* allocate ram for DB/mask/salt/hash of size modulus_len */
+ DB = XMALLOC(modulus_len);
+ mask = XMALLOC(modulus_len);
+ salt = XMALLOC(modulus_len);
+ hash = XMALLOC(modulus_len);
+ if (DB == NULL || mask == NULL || salt == NULL || hash == NULL) {
+ if (DB != NULL) {
+ XFREE(DB);
+ }
+ if (mask != NULL) {
+ XFREE(mask);
+ }
+ if (salt != NULL) {
+ XFREE(salt);
+ }
+ if (hash != NULL) {
+ XFREE(hash);
+ }
+ return CRYPT_MEM;
+ }
+
+ /* ensure the 0xBC byte */
+ if (sig[siglen-1] != 0xBC) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+
+ /* copy out the DB */
+ x = 0;
+ XMEMCPY(DB, sig + x, modulus_len - hLen - 1);
+ x += modulus_len - hLen - 1;
+
+ /* copy out the hash */
+ XMEMCPY(hash, sig + x, hLen);
+ x += hLen;
+
+ /* check the MSB */
+ if ((sig[0] & ~(0xFF >> ((modulus_len<<3) - (modulus_bitlen-1)))) != 0) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+
+ /* generate mask of length modulus_len - hLen - 1 from hash */
+ if ((err = pkcs_1_mgf1(hash_algo, hash, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* xor against DB */
+ for (y = 0; y < (modulus_len - hLen - 1); y++) {
+ DB[y] ^= mask[y];
+ }
+
+ /* now clear the first byte [make sure smaller than modulus] */
+ DB[0] &= 0xFF >> ((modulus_len<<3) - (modulus_bitlen-1));
+
+ /* DB = PS || 0x01 || salt, PS == modulus_len - saltlen - hLen - 2 zero bytes */
+
+ /* check for zeroes and 0x01 */
+ for (x = 0; x < modulus_len - saltlen - hLen - 2; x++) {
+ if (DB[x] != 0x00) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+ }
+
+ /* check for the 0x01 */
+ if (DB[x++] != 0x01) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+
+ zeromem(mask, 8);
+
+ /* M = (eight) 0x00 || msghash || salt, mask = H(M) */
+ err = hash_memory_multi(hash_algo, mask, &hLen, mask, (unsigned long)8, msghash, (unsigned long)msghashlen, DB+x, (unsigned long)saltlen, NULL, 0);
+ if (err != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* mask == hash means valid signature */
+ if (XMEMCMP(mask, hash, hLen) == 0) {
+ *res = 1;
+ }
+
+ err = CRYPT_OK;
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(DB, modulus_len);
+ zeromem(mask, modulus_len);
+ zeromem(salt, modulus_len);
+ zeromem(hash, modulus_len);
+#endif
+
+ XFREE(hash);
+ XFREE(salt);
+ XFREE(mask);
+ XFREE(DB);
+
+ return err;
+}
+
+#endif /* LTC_PKCS_1 */
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c,v $ */
+/* $Revision: 1.11 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_pss_encode.c b/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_pss_encode.c
new file mode 100644
index 0000000..9416eae
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_pss_encode.c
@@ -0,0 +1,157 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include <ncr-int.h>
+#include <linux/slab.h>
+
+/**
+ @file pkcs_1_pss_encode.c
+ LTC_PKCS #1 PSS Signature Padding, Tom St Denis
+*/
+
+#ifdef LTC_PKCS_1
+
+/**
+ LTC_PKCS #1 v2.00 Signature Encoding
+ @param msghash The hash to encode
+ @param msghashlen The length of the hash (octets)
+ @param saltlen The length of the salt desired (octets)
+ @param hash_algo The desired hash
+ @param modulus_bitlen The bit length of the RSA modulus
+ @param out [out] The destination of the encoding
+ @param outlen [in/out] The max size and resulting size of the encoded data
+ @return CRYPT_OK if successful
+*/
+int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen,
+ unsigned long saltlen, const struct algo_properties_st *hash_algo,
+ unsigned long modulus_bitlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned char *DB, *mask, *salt, *hash;
+ unsigned long x, y, hLen, modulus_len;
+ int err;
+
+ LTC_ARGCHK(msghash != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* ensure hash and PRNG are valid */
+ if ((err = hash_is_valid(hash_algo)) != CRYPT_OK) {
+ return err;
+ }
+
+ hLen = hash_algo->digest_size;
+ modulus_len = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0);
+
+ /* check sizes */
+ if ((saltlen > modulus_len) || (modulus_len < hLen + saltlen + 2)) {
+ return CRYPT_PK_INVALID_SIZE;
+ }
+
+ /* allocate ram for DB/mask/salt/hash of size modulus_len */
+ DB = XMALLOC(modulus_len);
+ mask = XMALLOC(modulus_len);
+ salt = XMALLOC(modulus_len);
+ hash = XMALLOC(modulus_len);
+ if (DB == NULL || mask == NULL || salt == NULL || hash == NULL) {
+ if (DB != NULL) {
+ XFREE(DB);
+ }
+ if (mask != NULL) {
+ XFREE(mask);
+ }
+ if (salt != NULL) {
+ XFREE(salt);
+ }
+ if (hash != NULL) {
+ XFREE(hash);
+ }
+ return CRYPT_MEM;
+ }
+
+
+ /* generate random salt */
+ if (saltlen > 0) {
+ get_random_bytes(salt, saltlen);
+ }
+
+ zeromem(DB, 8);
+
+ /* M = (eight) 0x00 || msghash || salt, hash = H(M) */
+ err = hash_memory_multi(hash_algo, hash, &hLen, DB, (unsigned long)8, msghash, (unsigned long)msghashlen, salt, (unsigned long)saltlen, NULL, 0);
+ if (err != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* generate DB = PS || 0x01 || salt, PS == modulus_len - saltlen - hLen - 2 zero bytes */
+ x = 0;
+ XMEMSET(DB + x, 0, modulus_len - saltlen - hLen - 2);
+ x += modulus_len - saltlen - hLen - 2;
+ DB[x++] = 0x01;
+ XMEMCPY(DB + x, salt, saltlen);
+ x += saltlen;
+
+ /* generate mask of length modulus_len - hLen - 1 from hash */
+ if ((err = pkcs_1_mgf1(hash_algo, hash, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* xor against DB */
+ for (y = 0; y < (modulus_len - hLen - 1); y++) {
+ DB[y] ^= mask[y];
+ }
+
+ /* output is DB || hash || 0xBC */
+ if (*outlen < modulus_len) {
+ *outlen = modulus_len;
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto LBL_ERR;
+ }
+
+ /* DB len = modulus_len - hLen - 1 */
+ y = 0;
+ XMEMCPY(out + y, DB, modulus_len - hLen - 1);
+ y += modulus_len - hLen - 1;
+
+ /* hash */
+ XMEMCPY(out + y, hash, hLen);
+ y += hLen;
+
+ /* 0xBC */
+ out[y] = 0xBC;
+
+ /* now clear the 8*modulus_len - modulus_bitlen most significant bits */
+ out[0] &= 0xFF >> ((modulus_len<<3) - (modulus_bitlen-1));
+
+ /* store output size */
+ *outlen = modulus_len;
+ err = CRYPT_OK;
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(DB, modulus_len);
+ zeromem(mask, modulus_len);
+ zeromem(salt, modulus_len);
+ zeromem(hash, modulus_len);
+#endif
+
+ XFREE(hash);
+ XFREE(salt);
+ XFREE(mask);
+ XFREE(DB);
+
+ return err;
+}
+
+#endif /* LTC_PKCS_1 */
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_encode.c,v $ */
+/* $Revision: 1.9 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_v1_5_decode.c b/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_v1_5_decode.c
new file mode 100644
index 0000000..1bb08e3
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_v1_5_decode.c
@@ -0,0 +1,110 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/** @file pkcs_1_v1_5_decode.c
+ *
+ * LTC_PKCS #1 v1.5 Padding. (Andreas Lange)
+ */
+
+#ifdef LTC_PKCS_1
+
+/** @brief LTC_PKCS #1 v1.5 decode.
+ *
+ * @param msg The encoded data to decode
+ * @param msglen The length of the encoded data (octets)
+ * @param block_type Block type to use in padding (\sa ltc_pkcs_1_v1_5_blocks)
+ * @param modulus_bitlen The bit length of the RSA modulus
+ * @param out [out] Destination of decoding
+ * @param outlen [in/out] The max size and resulting size of the decoding
+ * @param is_valid [out] Boolean whether the padding was valid
+ *
+ * @return CRYPT_OK if successful (even if invalid)
+ */
+int pkcs_1_v1_5_decode(const unsigned char *msg,
+ unsigned long msglen,
+ int block_type,
+ unsigned long modulus_bitlen,
+ unsigned char *out,
+ unsigned long *outlen,
+ int *is_valid)
+{
+ unsigned long modulus_len, ps_len, i;
+ int result;
+
+ /* default to invalid packet */
+ *is_valid = 0;
+
+ modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);
+
+ /* test message size */
+
+ if ((msglen > modulus_len) || (modulus_len < 11)) {
+ return CRYPT_PK_INVALID_SIZE;
+ }
+
+ /* separate encoded message */
+
+ if ((msg[0] != 0x00) || (msg[1] != (unsigned char)block_type)) {
+ result = CRYPT_INVALID_PACKET;
+ goto bail;
+ }
+
+ if (block_type == LTC_LTC_PKCS_1_EME) {
+ for (i = 2; i < modulus_len; i++) {
+ /* separator */
+ if (msg[i] == 0x00) { break; }
+ }
+ ps_len = i++ - 2;
+
+ if ((i >= modulus_len) || (ps_len < 8)) {
+ /* There was no octet with hexadecimal value 0x00 to separate ps from m,
+ * or the length of ps is less than 8 octets.
+ */
+ result = CRYPT_INVALID_PACKET;
+ goto bail;
+ }
+ } else {
+ for (i = 2; i < modulus_len - 1; i++) {
+ if (msg[i] != 0xFF) { break; }
+ }
+
+ /* separator check */
+ if (msg[i] != 0) {
+ /* There was no octet with hexadecimal value 0x00 to separate ps from m. */
+ result = CRYPT_INVALID_PACKET;
+ goto bail;
+ }
+
+ ps_len = i - 2;
+ }
+
+ if (*outlen < (msglen - (2 + ps_len + 1))) {
+ *outlen = msglen - (2 + ps_len + 1);
+ result = CRYPT_BUFFER_OVERFLOW;
+ goto bail;
+ }
+
+ *outlen = (msglen - (2 + ps_len + 1));
+ XMEMCPY(out, &msg[2 + ps_len + 1], *outlen);
+
+ /* valid packet */
+ *is_valid = 1;
+ result = CRYPT_OK;
+bail:
+ return result;
+} /* pkcs_1_v1_5_decode */
+
+#endif /* #ifdef LTC_PKCS_1 */
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_decode.c,v $ */
+/* $Revision: 1.7 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_v1_5_encode.c b/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_v1_5_encode.c
new file mode 100644
index 0000000..048fe69
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_v1_5_encode.c
@@ -0,0 +1,95 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/*! \file pkcs_1_v1_5_encode.c
+ *
+ * LTC_PKCS #1 v1.5 Padding (Andreas Lange)
+ */
+
+#ifdef LTC_PKCS_1
+
+/*! \brief LTC_PKCS #1 v1.5 encode.
+ *
+ * \param msg The data to encode
+ * \param msglen The length of the data to encode (octets)
+ * \param block_type Block type to use in padding (\sa ltc_pkcs_1_v1_5_blocks)
+ * \param modulus_bitlen The bit length of the RSA modulus
+ * \param out [out] The destination for the encoded data
+ * \param outlen [in/out] The max size and resulting size of the encoded data
+ *
+ * \return CRYPT_OK if successful
+ */
+int pkcs_1_v1_5_encode(const unsigned char *msg,
+ unsigned long msglen,
+ int block_type,
+ unsigned long modulus_bitlen,
+ unsigned char *out,
+ unsigned long *outlen)
+{
+ unsigned long modulus_len, ps_len, i;
+ unsigned char *ps;
+ int result;
+
+ /* valid block_type? */
+ if ((block_type != LTC_LTC_PKCS_1_EMSA) &&
+ (block_type != LTC_LTC_PKCS_1_EME)) {
+ return CRYPT_PK_INVALID_PADDING;
+ }
+
+ modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);
+
+ /* test message size */
+ if ((msglen + 11) > modulus_len) {
+ return CRYPT_PK_INVALID_SIZE;
+ }
+
+ if (*outlen < modulus_len) {
+ *outlen = modulus_len;
+ result = CRYPT_BUFFER_OVERFLOW;
+ goto bail;
+ }
+
+ /* generate an octets string PS */
+ ps = &out[2];
+ ps_len = modulus_len - msglen - 3;
+
+ if (block_type == LTC_LTC_PKCS_1_EME) {
+ /* now choose a random ps */
+ get_random_bytes(ps, ps_len);
+
+ /* transform zero bytes (if any) to non-zero random bytes */
+ for (i = 0; i < ps_len; i++) {
+ while (ps[i] == 0) {
+ get_random_bytes(&ps[i], 1);
+ }
+ }
+ } else {
+ XMEMSET(ps, 0xFF, ps_len);
+ }
+
+ /* create string of length modulus_len */
+ out[0] = 0x00;
+ out[1] = (unsigned char)block_type; /* block_type 1 or 2 */
+ out[2 + ps_len] = 0x00;
+ XMEMCPY(&out[2 + ps_len + 1], msg, msglen);
+ *outlen = modulus_len;
+
+ result = CRYPT_OK;
+bail:
+ return result;
+} /* pkcs_1_v1_5_encode */
+
+#endif /* #ifdef LTC_PKCS_1 */
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_encode.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/rsa/rsa_decrypt_key.c b/crypto/userspace/libtomcrypt/pk/rsa/rsa_decrypt_key.c
new file mode 100644
index 0000000..ba16e32
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/rsa/rsa_decrypt_key.c
@@ -0,0 +1,107 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include "ncr-int.h"
+#include <linux/slab.h>
+
+/**
+ @file rsa_decrypt_key.c
+ RSA LTC_PKCS #1 Decryption, Tom St Denis and Andreas Lange
+*/
+
+#ifdef LTC_MRSA
+
+/**
+ LTC_PKCS #1 decrypt then v1.5 or OAEP depad
+ @param in The ciphertext
+ @param inlen The length of the ciphertext (octets)
+ @param out [out] The plaintext
+ @param outlen [in/out] The max size and resulting size of the plaintext (octets)
+ @param lparam The system "lparam" value
+ @param lparamlen The length of the lparam value (octets)
+ @param hash The desired hash
+ @param padding Type of padding (LTC_LTC_PKCS_1_OAEP or LTC_LTC_PKCS_1_V1_5)
+ @param stat [out] Result of the decryption, 1==valid, 0==invalid
+ @param key The corresponding private RSA key
+ @return CRYPT_OK if succcessul (even if invalid)
+*/
+int rsa_decrypt_key_ex(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ const unsigned char *lparam, unsigned long lparamlen,
+ const struct algo_properties_st *hash, int padding,
+ int *stat, rsa_key *key)
+{
+ unsigned long modulus_bitlen, modulus_bytelen, x;
+ int err;
+ unsigned char *tmp;
+
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(stat != NULL);
+
+ /* default to invalid */
+ *stat = 0;
+
+ /* valid padding? */
+
+ if ((padding != LTC_LTC_PKCS_1_V1_5) &&
+ (padding != LTC_LTC_PKCS_1_OAEP)) {
+ return CRYPT_PK_INVALID_PADDING;
+ }
+
+ if (padding == LTC_LTC_PKCS_1_OAEP) {
+ /* valid hash ? */
+ if ((err = hash_is_valid(hash)) != CRYPT_OK) {
+ return err;
+ }
+ }
+
+ /* get modulus len in bits */
+ modulus_bitlen = mp_count_bits( (&key->N));
+
+ /* outlen must be at least the size of the modulus */
+ modulus_bytelen = mp_unsigned_bin_size( (&key->N));
+ if (modulus_bytelen != inlen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* allocate ram */
+ tmp = XMALLOC(inlen);
+ if (tmp == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* rsa decode the packet */
+ x = inlen;
+ if ((err = rsa_exptmod(in, inlen, tmp, &x, PK_PRIVATE, key)) != CRYPT_OK) {
+ XFREE(tmp);
+ return err;
+ }
+
+ if (padding == LTC_LTC_PKCS_1_OAEP) {
+ /* now OAEP decode the packet */
+ err = pkcs_1_oaep_decode(tmp, x, lparam, lparamlen, modulus_bitlen, hash,
+ out, outlen, stat);
+ } else {
+ /* now LTC_PKCS #1 v1.5 depad the packet */
+ err = pkcs_1_v1_5_decode(tmp, x, LTC_LTC_PKCS_1_EME, modulus_bitlen, out, outlen, stat);
+ }
+
+ XFREE(tmp);
+ return err;
+}
+
+#endif /* LTC_MRSA */
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_decrypt_key.c,v $ */
+/* $Revision: 1.10 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/rsa/rsa_encrypt_key.c b/crypto/userspace/libtomcrypt/pk/rsa/rsa_encrypt_key.c
new file mode 100644
index 0000000..8d3f2db
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/rsa/rsa_encrypt_key.c
@@ -0,0 +1,96 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include "ncr-int.h"
+
+/**
+ @file rsa_encrypt_key.c
+ RSA LTC_PKCS #1 encryption, Tom St Denis and Andreas Lange
+*/
+
+#ifdef LTC_MRSA
+
+/**
+ (LTC_PKCS #1 v2.0) OAEP pad then encrypt
+ @param in The plaintext
+ @param inlen The length of the plaintext (octets)
+ @param out [out] The ciphertext
+ @param outlen [in/out] The max size and resulting size of the ciphertext
+ @param lparam The system "lparam" for the encryption
+ @param lparamlen The length of lparam (octets)
+ @param hash The desired hash
+ @param padding Type of padding (LTC_LTC_PKCS_1_OAEP or LTC_LTC_PKCS_1_V1_5)
+ @param key The RSA key to encrypt to
+ @return CRYPT_OK if successful
+*/
+int rsa_encrypt_key_ex(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ const unsigned char *lparam, unsigned long lparamlen,
+ const struct algo_properties_st *hash, int padding, rsa_key *key)
+{
+ unsigned long modulus_bitlen, modulus_bytelen, x;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* valid padding? */
+ if ((padding != LTC_LTC_PKCS_1_V1_5) &&
+ (padding != LTC_LTC_PKCS_1_OAEP)) {
+ return CRYPT_PK_INVALID_PADDING;
+ }
+
+ if (padding == LTC_LTC_PKCS_1_OAEP) {
+ /* valid hash? */
+ if ((err = hash_is_valid(hash)) != CRYPT_OK) {
+ return err;
+ }
+ }
+
+ /* get modulus len in bits */
+ modulus_bitlen = mp_count_bits( (&key->N));
+
+ /* outlen must be at least the size of the modulus */
+ modulus_bytelen = mp_unsigned_bin_size( (&key->N));
+ if (modulus_bytelen > *outlen) {
+ *outlen = modulus_bytelen;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ if (padding == LTC_LTC_PKCS_1_OAEP) {
+ /* OAEP pad the key */
+ x = *outlen;
+ if ((err = pkcs_1_oaep_encode(in, inlen, lparam,
+ lparamlen, modulus_bitlen, hash,
+ out, &x)) != CRYPT_OK) {
+ return err;
+ }
+ } else {
+ /* LTC_PKCS #1 v1.5 pad the key */
+ x = *outlen;
+ if ((err = pkcs_1_v1_5_encode(in, inlen, LTC_LTC_PKCS_1_EME,
+ modulus_bitlen,
+ out, &x)) != CRYPT_OK) {
+ return err;
+ }
+ }
+
+ /* rsa exptmod the OAEP or LTC_PKCS #1 v1.5 pad */
+ return rsa_exptmod(out, x, out, outlen, PK_PUBLIC, key);
+}
+
+#endif /* LTC_MRSA */
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_encrypt_key.c,v $ */
+/* $Revision: 1.10 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/rsa/rsa_export.c b/crypto/userspace/libtomcrypt/pk/rsa/rsa_export.c
new file mode 100644
index 0000000..c5e8ff0
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/rsa/rsa_export.c
@@ -0,0 +1,87 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include <ncr-int.h>
+#include <linux/slab.h>
+/**
+ @file rsa_export.c
+ Export RSA LTC_PKCS keys, Tom St Denis
+*/
+
+#ifdef LTC_MRSA
+
+/**
+ This will export either an RSAPublicKey or RSAPrivateKey [defined in LTC_PKCS #1 v2.1]
+ @param out [out] Destination of the packet
+ @param outlen [in/out] The max size and resulting size of the packet
+ @param type The type of exported key (PK_PRIVATE or PK_PUBLIC)
+ @param key The RSA key to export
+ @return CRYPT_OK if successful
+*/
+int rsa_export(unsigned char *out, unsigned long *outlen, int type, rsa_key *key)
+{
+ unsigned long zero=0;
+ int err;
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* type valid? */
+ if (!(key->type == PK_PRIVATE) && (type == PK_PRIVATE)) {
+ return CRYPT_PK_INVALID_TYPE;
+ }
+
+ if (type == PK_PRIVATE) {
+ /* private key */
+ /* output is
+ Version, n, e, d, p, q, d mod (p-1), d mod (q - 1), 1/q mod p
+ */
+ return der_encode_sequence_multi(out, outlen,
+ LTC_ASN1_SHORT_INTEGER, 1UL, &zero,
+ LTC_ASN1_INTEGER, 1UL, &key->N,
+ LTC_ASN1_INTEGER, 1UL, &key->e,
+ LTC_ASN1_INTEGER, 1UL, &key->d,
+ LTC_ASN1_INTEGER, 1UL, &key->p,
+ LTC_ASN1_INTEGER, 1UL, &key->q,
+ LTC_ASN1_INTEGER, 1UL, &key->dP,
+ LTC_ASN1_INTEGER, 1UL, &key->dQ,
+ LTC_ASN1_INTEGER, 1UL, &key->qP,
+ LTC_ASN1_EOL, 0UL, NULL);
+ } else {
+ unsigned long tmplen = (mp_count_bits(&key->N)/8)*2+8;
+ unsigned char* tmp = XMALLOC(tmplen);
+
+ if (tmp == NULL) {
+ return CRYPT_MEM;
+ }
+
+ err = der_encode_sequence_multi(tmp, &tmplen,
+ LTC_ASN1_INTEGER, 1UL, &key->N,
+ LTC_ASN1_INTEGER, 1UL, &key->e,
+ LTC_ASN1_EOL, 0UL, NULL);
+ if (err != CRYPT_OK) {
+ goto error;
+ }
+
+ err = der_encode_subject_public_key_info(out, outlen,
+ PKA_RSA, tmp, tmplen, LTC_ASN1_NULL, NULL, 0);
+
+error:
+ XFREE(tmp);
+ return err;
+ }
+}
+
+#endif /* LTC_MRSA */
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_export.c,v $ */
+/* $Revision: 1.17 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/rsa/rsa_exptmod.c b/crypto/userspace/libtomcrypt/pk/rsa/rsa_exptmod.c
new file mode 100644
index 0000000..35ebfe3
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/rsa/rsa_exptmod.c
@@ -0,0 +1,147 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ *
+ * Added RSA blinding --nmav
+ */
+#include "tomcrypt.h"
+
+/**
+ @file rsa_exptmod.c
+ RSA LTC_PKCS exptmod, Tom St Denis
+*/
+
+#ifdef LTC_MRSA
+
+/**
+ Compute an RSA modular exponentiation
+ @param in The input data to send into RSA
+ @param inlen The length of the input (octets)
+ @param out [out] The destination
+ @param outlen [in/out] The max size and resulting size of the output
+ @param which Which exponent to use, e.g. PK_PRIVATE or PK_PUBLIC
+ @param key The RSA key to use
+ @return CRYPT_OK if successful
+*/
+int rsa_exptmod(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen, int which,
+ rsa_key *key)
+{
+ mp_int tmp, tmpa, tmpb, rnd, rndi /* inverse of rnd */;
+ unsigned long x;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* is the key of the right type for the operation? */
+ if (which == PK_PRIVATE && (key->type != PK_PRIVATE)) {
+ return CRYPT_PK_NOT_PRIVATE;
+ }
+
+ /* must be a private or public operation */
+ if (which != PK_PRIVATE && which != PK_PUBLIC) {
+ return CRYPT_PK_INVALID_TYPE;
+ }
+
+ /* init and copy into tmp */
+ if ((err = mp_init_multi(&tmp, &tmpa, &tmpb, &rnd, &rndi, NULL)) != CRYPT_OK)
+ { return err; }
+ if ((err = mp_read_unsigned_bin(&tmp, (unsigned char *)in, (int)inlen)) != CRYPT_OK)
+ { goto error; }
+
+ /* sanity check on the input */
+ if (mp_cmp(&key->N, &tmp) == LTC_MP_LT) {
+ err = CRYPT_PK_INVALID_SIZE;
+ goto error;
+ }
+
+ /* are we using the private exponent and is the key optimized? */
+ if (which == PK_PRIVATE) {
+ /* do blinding */
+ err = mp_rand(&rnd, mp_count_bits(&key->N));
+ if (err != CRYPT_OK) {
+ goto error;
+ }
+
+ /* rndi = 1/rnd mod N */
+ err = mp_invmod( &rnd, &key->N, &rndi);
+ if (err != CRYPT_OK) {
+ goto error;
+ }
+
+ /* rnd = rnd^e */
+ err = mp_exptmod( &rnd, &key->e, &key->N, &rnd);
+ if (err != CRYPT_OK) {
+ goto error;
+ }
+
+ /* tmp = tmp*rnd mod N */
+ err = mp_mulmod( &tmp, &rnd, &key->N, &tmp);
+ if (err != CRYPT_OK) {
+ goto error;
+ }
+
+ /* tmpa = tmp^dP mod p */
+ if ((err = mp_exptmod(&tmp, &key->dP, &key->p, &tmpa)) != CRYPT_OK) { goto error; }
+
+ /* tmpb = tmp^dQ mod q */
+ if ((err = mp_exptmod(&tmp, &key->dQ, &key->q, &tmpb)) != CRYPT_OK) { goto error; }
+
+ /* tmp = (tmpa - tmpb) * qInv (mod p) */
+ if ((err = mp_sub(&tmpa, &tmpb, &tmp)) != CRYPT_OK) { goto error; }
+ if ((err = mp_mulmod(&tmp, &key->qP, &key->p, &tmp)) != CRYPT_OK) { goto error; }
+
+ /* tmp = tmpb + q * tmp */
+ if ((err = mp_mul(&tmp, &key->q, &tmp)) != CRYPT_OK) { goto error; }
+ if ((err = mp_add(&tmp, &tmpb, &tmp)) != CRYPT_OK) { goto error; }
+
+ /* unblind */
+ err = mp_mulmod( &tmp, &rndi, &key->N, &tmp);
+ if (err != CRYPT_OK) {
+ goto error;
+ }
+ } else {
+ /* exptmod it */
+ if ((err = mp_exptmod(&tmp, &key->e, &key->N, &tmp)) != CRYPT_OK) { goto error; }
+ }
+
+ /* read it back */
+ x = (unsigned long)mp_unsigned_bin_size(&key->N);
+ if (x > *outlen) {
+ *outlen = x;
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto error;
+ }
+
+ /* this should never happen ... */
+ if (mp_unsigned_bin_size(&tmp) > mp_unsigned_bin_size(&key->N)) {
+ err = CRYPT_ERROR;
+ goto error;
+ }
+ *outlen = x;
+
+ /* convert it */
+ zeromem(out, x);
+ if ((err = mp_to_unsigned_bin(&tmp, out+(x-mp_unsigned_bin_size(&tmp)))) != CRYPT_OK) { goto error; }
+
+ /* clean up and return */
+ err = CRYPT_OK;
+error:
+ mp_clear_multi(&tmp, &tmpa, &tmpb, &rnd, &rndi, NULL);
+ return err;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_exptmod.c,v $ */
+/* $Revision: 1.18 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/rsa/rsa_free.c b/crypto/userspace/libtomcrypt/pk/rsa/rsa_free.c
new file mode 100644
index 0000000..d38b266
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/rsa/rsa_free.c
@@ -0,0 +1,34 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file rsa_free.c
+ Free an RSA key, Tom St Denis
+*/
+
+#ifdef LTC_MRSA
+
+/**
+ Free an RSA key from memory
+ @param key The RSA key to free
+*/
+void rsa_free(rsa_key *key)
+{
+ LTC_ARGCHKVD(key != NULL);
+ mp_clear_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, &key->p, &key->q, NULL);
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_free.c,v $ */
+/* $Revision: 1.10 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/rsa/rsa_import.c b/crypto/userspace/libtomcrypt/pk/rsa/rsa_import.c
new file mode 100644
index 0000000..8bd8c47
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/rsa/rsa_import.c
@@ -0,0 +1,128 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include <linux/slab.h>
+
+/**
+ @file rsa_import.c
+ Import a LTC_PKCS RSA key, Tom St Denis
+*/
+
+#ifdef LTC_MRSA
+
+/**
+ Import an RSAPublicKey or RSAPrivateKey [two-prime only, only support >= 1024-bit keys, defined in LTC_PKCS #1 v2.1]
+ @param in The packet to import from
+ @param inlen It's length (octets)
+ @param key [out] Destination for newly imported key
+ @return CRYPT_OK if successful, upon error allocated memory is freed
+*/
+int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key)
+{
+ int err;
+ mp_int zero;
+ unsigned char *tmpbuf=NULL;
+ unsigned long tmpbuf_len;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* init key */
+ if ((err = mp_init_multi(&key->e, &key->d, &key->N, &key->dQ,
+ &key->dP, &key->qP, &key->p, &key->q, NULL)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* see if the OpenSSL DER format RSA public key will work */
+ tmpbuf_len = MAX_RSA_SIZE * 8;
+ tmpbuf = XCALLOC(1, tmpbuf_len);
+ if (tmpbuf == NULL) {
+ err = CRYPT_MEM;
+ goto LBL_ERR;
+ }
+
+ err = der_decode_subject_public_key_info(in, inlen,
+ PKA_RSA, tmpbuf, &tmpbuf_len,
+ LTC_ASN1_NULL, NULL, 0);
+
+ if (err == CRYPT_OK) { /* SubjectPublicKeyInfo format */
+
+ /* now it should be SEQUENCE { INTEGER, INTEGER } */
+ if ((err = der_decode_sequence_multi(tmpbuf, tmpbuf_len,
+ LTC_ASN1_INTEGER, 1UL, &key->N,
+ LTC_ASN1_INTEGER, 1UL, &key->e,
+ LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ XFREE(tmpbuf);
+
+ key->type = PK_PUBLIC;
+ return CRYPT_OK;
+ }
+
+ XFREE(tmpbuf);
+
+ /* not SSL public key, try to match against LTC_PKCS #1 standards */
+ if ((err = der_decode_sequence_multi(in, inlen,
+ LTC_ASN1_INTEGER, 1UL, &key->N,
+ LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ if (mp_cmp_d(&key->N, 0) == LTC_MP_EQ) {
+ if ((err = mp_init(&zero)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ /* it's a private key */
+ if ((err = der_decode_sequence_multi(in, inlen,
+ LTC_ASN1_INTEGER, 1UL, zero,
+ LTC_ASN1_INTEGER, 1UL, &key->N,
+ LTC_ASN1_INTEGER, 1UL, &key->e,
+ LTC_ASN1_INTEGER, 1UL, &key->d,
+ LTC_ASN1_INTEGER, 1UL, &key->p,
+ LTC_ASN1_INTEGER, 1UL, &key->q,
+ LTC_ASN1_INTEGER, 1UL, &key->dP,
+ LTC_ASN1_INTEGER, 1UL, &key->dQ,
+ LTC_ASN1_INTEGER, 1UL, &key->qP,
+ LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
+ mp_clear(&zero);
+ goto LBL_ERR;
+ }
+ mp_clear(&zero);
+ key->type = PK_PRIVATE;
+ } else if (mp_cmp_d(&key->N, 1) == LTC_MP_EQ) {
+ /* we don't support multi-prime RSA */
+ err = CRYPT_PK_INVALID_TYPE;
+ goto LBL_ERR;
+ } else {
+ /* it's a public key and we lack e */
+ if ((err = der_decode_sequence_multi(in, inlen,
+ LTC_ASN1_INTEGER, 1UL, &key->N,
+ LTC_ASN1_INTEGER, 1UL, &key->e,
+ LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ key->type = PK_PUBLIC;
+ }
+ return CRYPT_OK;
+LBL_ERR:
+ XFREE(tmpbuf);
+ mp_clear_multi(&key->d, &key->e, &key->N, &key->dQ, &key->dP, &key->qP, &key->p, &key->q, NULL);
+ return err;
+}
+
+#endif /* LTC_MRSA */
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_import.c,v $ */
+/* $Revision: 1.23 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/rsa/rsa_make_key.c b/crypto/userspace/libtomcrypt/pk/rsa/rsa_make_key.c
new file mode 100644
index 0000000..6718f09
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/rsa/rsa_make_key.c
@@ -0,0 +1,105 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file rsa_make_key.c
+ RSA key generation, Tom St Denis
+*/
+
+#ifdef LTC_MRSA
+
+/**
+ Create an RSA key
+ @param size The size of the modulus (key size) desired (octets)
+ @param e The "e" value (public key). e==65537 is a good choice
+ @param key [out] Destination of a newly created private key pair
+ @return CRYPT_OK if successful, upon error all allocated ram is freed
+*/
+int rsa_make_key(int size, long e, rsa_key *key)
+{
+ mp_int p, q, tmp1, tmp2, tmp3;
+ int err;
+
+ LTC_ARGCHK(key != NULL);
+
+ if ((size < (MIN_RSA_SIZE/8)) || (size > (MAX_RSA_SIZE/8))) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+
+ if ((e < 3) || ((e & 1) == 0)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ if ((err = mp_init_multi(&p, &q, &tmp1, &tmp2, &tmp3, NULL)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* make primes p and q (optimization provided by Wayne Scott) */
+ if ((err = mp_set_int(&tmp3, e)) != CRYPT_OK) { goto cleanup; } /* tmp3 = e */
+
+ /* make prime "p" */
+ do {
+ if ((err = rand_prime( &p, size/2)) != CRYPT_OK) { goto cleanup; }
+ if ((err = mp_sub_d( &p, 1, &tmp1)) != CRYPT_OK) { goto cleanup; } /* tmp1 = p-1 */
+ if ((err = mp_gcd( &tmp1, &tmp3, &tmp2)) != CRYPT_OK) { goto cleanup; } /* tmp2 = gcd(p-1, e) */
+ } while (mp_cmp_d( &tmp2, 1) != 0); /* while e divides p-1 */
+
+ /* make prime "q" */
+ do {
+ if ((err = rand_prime( &q, size/2)) != CRYPT_OK) { goto cleanup; }
+ if ((err = mp_sub_d( &q, 1, &tmp1)) != CRYPT_OK) { goto cleanup; } /* tmp1 = q-1 */
+ if ((err = mp_gcd( &tmp1, &tmp3, &tmp2)) != CRYPT_OK) { goto cleanup; } /* tmp2 = gcd(q-1, e) */
+ } while (mp_cmp_d( &tmp2, 1) != 0); /* while e divides q-1 */
+
+ /* tmp1 = lcm(p-1, q-1) */
+ if ((err = mp_sub_d( &p, 1, &tmp2)) != CRYPT_OK) { goto cleanup; } /* tmp2 = p-1 */
+ /* tmp1 = q-1 (previous do/while loop) */
+ if ((err = mp_lcm( &tmp1, &tmp2, &tmp1)) != CRYPT_OK) { goto cleanup; } /* tmp1 = lcm(p-1, q-1) */
+
+ /* make key */
+ if ((err = mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, &key->p, &key->q, NULL)) != CRYPT_OK) {
+ goto cleanup;
+ }
+
+ if ((err = mp_set_int( &key->e, e)) != CRYPT_OK) { goto errkey; } /* key->e = e */
+ if ((err = mp_invmod( &key->e, &tmp1, &key->d)) != CRYPT_OK) { goto errkey; } /* key->d = 1/e mod lcm(p-1,q-1) */
+ if ((err = mp_mul( &p, &q, &key->N)) != CRYPT_OK) { goto errkey; } /* key->N = pq */
+
+ /* optimize for CRT now */
+ /* find d mod q-1 and d mod p-1 */
+ if ((err = mp_sub_d( &p, 1, &tmp1)) != CRYPT_OK) { goto errkey; } /* tmp1 = q-1 */
+ if ((err = mp_sub_d( &q, 1, &tmp2)) != CRYPT_OK) { goto errkey; } /* tmp2 = p-1 */
+ if ((err = mp_mod( &key->d, &tmp1, &key->dP)) != CRYPT_OK) { goto errkey; } /* dP = d mod p-1 */
+ if ((err = mp_mod( &key->d, &tmp2, &key->dQ)) != CRYPT_OK) { goto errkey; } /* dQ = d mod q-1 */
+ if ((err = mp_invmod( &q, &p, &key->qP)) != CRYPT_OK) { goto errkey; } /* qP = 1/q mod p */
+
+ if ((err = mp_copy( &p, &key->p)) != CRYPT_OK) { goto errkey; }
+ if ((err = mp_copy( &q, &key->q)) != CRYPT_OK) { goto errkey; }
+
+ /* set key type (in this case it's CRT optimized) */
+ key->type = PK_PRIVATE;
+
+ /* return ok and free temps */
+ err = CRYPT_OK;
+ goto cleanup;
+errkey:
+ mp_clear_multi(&key->d, &key->e, &key->N, &key->dQ, &key->dP, &key->qP, &key->p, &key->q, NULL);
+cleanup:
+ mp_clear_multi(&tmp3, &tmp2, &tmp1, &p, &q, NULL);
+ return err;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_make_key.c,v $ */
+/* $Revision: 1.16 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/rsa/rsa_sign_hash.c b/crypto/userspace/libtomcrypt/pk/rsa/rsa_sign_hash.c
new file mode 100644
index 0000000..b3c2f5b
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/rsa/rsa_sign_hash.c
@@ -0,0 +1,130 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include "ncr-int.h"
+#include <linux/slab.h>
+
+/**
+ @file rsa_sign_hash.c
+ RSA LTC_PKCS #1 v1.5 and v2 PSS sign hash, Tom St Denis and Andreas Lange
+*/
+
+#ifdef LTC_MRSA
+
+/**
+ LTC_PKCS #1 pad then sign
+ @param in The hash to sign
+ @param inlen The length of the hash to sign (octets)
+ @param out [out] The signature
+ @param outlen [in/out] The max size and resulting size of the signature
+ @param padding Type of padding (LTC_LTC_PKCS_1_PSS or LTC_LTC_PKCS_1_V1_5)
+ @param hash The desired hash
+ @param saltlen The length of the salt desired (octets)
+ @param key The private RSA key to use
+ @return CRYPT_OK if successful
+*/
+int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ int padding,
+ const struct algo_properties_st *hash, unsigned long saltlen,
+ rsa_key *key)
+{
+ unsigned long modulus_bitlen, modulus_bytelen, x, y;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* valid padding? */
+ if ((padding != LTC_LTC_PKCS_1_V1_5) && (padding != LTC_LTC_PKCS_1_PSS)) {
+ return CRYPT_PK_INVALID_PADDING;
+ }
+
+ if (padding == LTC_LTC_PKCS_1_PSS) {
+ if ((err = hash_is_valid(hash)) != CRYPT_OK) {
+ return err;
+ }
+ }
+
+ /* get modulus len in bits */
+ modulus_bitlen = mp_count_bits((&key->N));
+
+ /* outlen must be at least the size of the modulus */
+ modulus_bytelen = mp_unsigned_bin_size((&key->N));
+ if (modulus_bytelen > *outlen) {
+ *outlen = modulus_bytelen;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ if (padding == LTC_LTC_PKCS_1_PSS) {
+ /* PSS pad the key */
+ x = *outlen;
+ if ((err = pkcs_1_pss_encode(in, inlen, saltlen,
+ hash, modulus_bitlen, out, &x)) != CRYPT_OK) {
+ return err;
+ }
+ } else {
+ /* LTC_PKCS #1 v1.5 pad the hash */
+ unsigned char *tmpin;
+ ltc_asn1_list digestinfo[2], siginfo[2];
+ oid_st st;
+
+ /* not all hashes have OIDs... so sad */
+ if (hash_get_oid(hash, &st) != CRYPT_OK) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* construct the SEQUENCE
+ SEQUENCE {
+ SEQUENCE {hashoid OID
+ blah NULL
+ }
+ hash OCTET STRING
+ }
+ */
+ LTC_SET_ASN1(digestinfo, 0, LTC_ASN1_OBJECT_IDENTIFIER, st.OID, st.OIDlen);
+ LTC_SET_ASN1(digestinfo, 1, LTC_ASN1_NULL, NULL, 0);
+ LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 2);
+ LTC_SET_ASN1(siginfo, 1, LTC_ASN1_OCTET_STRING, in, inlen);
+
+ /* allocate memory for the encoding */
+ y = mp_unsigned_bin_size(&key->N);
+ tmpin = XMALLOC(y);
+ if (tmpin == NULL) {
+ return CRYPT_MEM;
+ }
+
+ if ((err = der_encode_sequence(siginfo, 2, tmpin, &y)) != CRYPT_OK) {
+ XFREE(tmpin);
+ return err;
+ }
+
+ x = *outlen;
+ if ((err = pkcs_1_v1_5_encode(tmpin, y, LTC_LTC_PKCS_1_EMSA,
+ modulus_bitlen,
+ out, &x)) != CRYPT_OK) {
+ XFREE(tmpin);
+ return err;
+ }
+ XFREE(tmpin);
+ }
+
+ /* RSA encode it */
+ return rsa_exptmod(out, x, out, outlen, PK_PRIVATE, key);
+}
+
+#endif /* LTC_MRSA */
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_sign_hash.c,v $ */
+/* $Revision: 1.11 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/rsa/rsa_verify_hash.c b/crypto/userspace/libtomcrypt/pk/rsa/rsa_verify_hash.c
new file mode 100644
index 0000000..b9ef89f
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/rsa/rsa_verify_hash.c
@@ -0,0 +1,170 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include "ncr-int.h"
+#include <linux/slab.h>
+
+/**
+ @file rsa_verify_hash.c
+ RSA LTC_PKCS #1 v1.5 or v2 PSS signature verification, Tom St Denis and Andreas Lange
+*/
+
+#ifdef LTC_MRSA
+
+/**
+ LTC_PKCS #1 de-sign then v1.5 or PSS depad
+ @param sig The signature data
+ @param siglen The length of the signature data (octets)
+ @param hash The hash of the message that was signed
+ @param hashlen The length of the hash of the message that was signed (octets)
+ @param padding Type of padding (LTC_LTC_PKCS_1_PSS or LTC_LTC_PKCS_1_V1_5)
+ @param hash_algo The desired hash
+ @param saltlen The length of the salt used during signature
+ @param stat [out] The result of the signature comparison, 1==valid, 0==invalid
+ @param key The public RSA key corresponding to the key that performed the signature
+ @return CRYPT_OK on success (even if the signature is invalid)
+*/
+int rsa_verify_hash_ex(const unsigned char *sig, unsigned long siglen,
+ const unsigned char *hash, unsigned long hashlen,
+ int padding,
+ const struct algo_properties_st *hash_algo, unsigned long saltlen,
+ int *stat, rsa_key *key)
+{
+ unsigned long modulus_bitlen, modulus_bytelen, x;
+ int err;
+ unsigned char *tmpbuf;
+
+ LTC_ARGCHK(hash != NULL);
+ LTC_ARGCHK(sig != NULL);
+ LTC_ARGCHK(stat != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* default to invalid */
+ *stat = 0;
+
+ /* valid padding? */
+
+ if ((padding != LTC_LTC_PKCS_1_V1_5) &&
+ (padding != LTC_LTC_PKCS_1_PSS)) {
+ return CRYPT_PK_INVALID_PADDING;
+ }
+
+ if (padding == LTC_LTC_PKCS_1_PSS) {
+ /* valid hash ? */
+ if ((err = hash_is_valid(hash_algo)) != CRYPT_OK) {
+ return err;
+ }
+ }
+
+ /* get modulus len in bits */
+ modulus_bitlen = mp_count_bits( (&key->N));
+
+ /* outlen must be at least the size of the modulus */
+ modulus_bytelen = mp_unsigned_bin_size( (&key->N));
+ if (modulus_bytelen != siglen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* allocate temp buffer for decoded sig */
+ tmpbuf = XMALLOC(siglen);
+ if (tmpbuf == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* RSA decode it */
+ x = siglen;
+ if ((err = rsa_exptmod(sig, siglen, tmpbuf, &x, PK_PUBLIC, key)) != CRYPT_OK) {
+ XFREE(tmpbuf);
+ return err;
+ }
+
+ /* make sure the output is the right size */
+ if (x != siglen) {
+ XFREE(tmpbuf);
+ return CRYPT_INVALID_PACKET;
+ }
+
+ if (padding == LTC_LTC_PKCS_1_PSS) {
+ /* PSS decode and verify it */
+ err = pkcs_1_pss_decode(hash, hashlen, tmpbuf, x, saltlen, hash_algo, modulus_bitlen, stat);
+ } else {
+ /* LTC_PKCS #1 v1.5 decode it */
+ unsigned char *out;
+ unsigned long outlen, loid[16];
+ int decoded;
+ ltc_asn1_list digestinfo[2], siginfo[2];
+ oid_st st;
+
+ /* not all hashes have OIDs... so sad */
+ if (hash_get_oid(hash_algo, &st) != CRYPT_OK) {
+ err = CRYPT_INVALID_ARG;
+ goto bail_2;
+ }
+
+ /* allocate temp buffer for decoded hash */
+ outlen = ((modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0)) - 3;
+ out = XMALLOC(outlen);
+ if (out == NULL) {
+ err = CRYPT_MEM;
+ goto bail_2;
+ }
+
+ if ((err = pkcs_1_v1_5_decode(tmpbuf, x, LTC_LTC_PKCS_1_EMSA, modulus_bitlen, out, &outlen, &decoded)) != CRYPT_OK) {
+ XFREE(out);
+ goto bail_2;
+ }
+
+ /* now we must decode out[0...outlen-1] using ASN.1, test the OID and then test the hash */
+ /* construct the SEQUENCE
+ SEQUENCE {
+ SEQUENCE {hashoid OID
+ blah NULL
+ }
+ hash OCTET STRING
+ }
+ */
+ LTC_SET_ASN1(digestinfo, 0, LTC_ASN1_OBJECT_IDENTIFIER, loid, sizeof(loid)/sizeof(loid[0]));
+ LTC_SET_ASN1(digestinfo, 1, LTC_ASN1_NULL, NULL, 0);
+ LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 2);
+ LTC_SET_ASN1(siginfo, 1, LTC_ASN1_OCTET_STRING, tmpbuf, siglen);
+
+ if ((err = der_decode_sequence(out, outlen, siginfo, 2)) != CRYPT_OK) {
+ XFREE(out);
+ goto bail_2;
+ }
+
+ /* test OID */
+ if ((digestinfo[0].size == st.OIDlen) &&
+ (XMEMCMP(digestinfo[0].data, st.OID, sizeof(unsigned long) * st.OIDlen) == 0) &&
+ (siginfo[1].size == hashlen) &&
+ (XMEMCMP(siginfo[1].data, hash, hashlen) == 0)) {
+ *stat = 1;
+ }
+
+#ifdef LTC_CLEAN_STACK
+ zeromem(out, outlen);
+#endif
+ XFREE(out);
+ }
+
+bail_2:
+#ifdef LTC_CLEAN_STACK
+ zeromem(tmpbuf, siglen);
+#endif
+ XFREE(tmpbuf);
+ return err;
+}
+
+#endif /* LTC_MRSA */
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_verify_hash.c,v $ */
+/* $Revision: 1.13 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
--
1.7.2.1

2010-08-20 08:45:55

by Miloslav Trmac

[permalink] [raw]
Subject: [PATCH 11/19] Add algorithm properties table.

Pointers to this table are used to identify algorithms throughout the
code.
---
crypto/userspace/Makefile | 2 +-
crypto/userspace/ncr-sessions.c | 150 +++++++++++++++++++++++++++++++++++++++
2 files changed, 151 insertions(+), 1 deletions(-)
create mode 100644 crypto/userspace/ncr-sessions.c

diff --git a/crypto/userspace/Makefile b/crypto/userspace/Makefile
index 81e4122..0891c2b 100644
--- a/crypto/userspace/Makefile
+++ b/crypto/userspace/Makefile
@@ -64,7 +64,7 @@ TOMCRYPT_OBJECTS = libtomcrypt/misc/zeromem.o libtomcrypt/misc/crypt/crypt_argch
libtomcrypt/pk/asn1/der/x509/der_decode_subject_public_key_info.o

cryptodev-objs := cryptodev_main.o cryptodev_cipher.o ncr-limits.o \
- utils.o $(TOMMATH_OBJECTS) \
+ ncr-sessions.o utils.o $(TOMMATH_OBJECTS) \
$(TOMCRYPT_OBJECTS)


diff --git a/crypto/userspace/ncr-sessions.c b/crypto/userspace/ncr-sessions.c
new file mode 100644
index 0000000..e6fd995
--- /dev/null
+++ b/crypto/userspace/ncr-sessions.c
@@ -0,0 +1,150 @@
+/*
+ * New driver for /dev/crypto device (aka CryptoDev)
+
+ * Copyright (c) 2010 Katholieke Universiteit Leuven
+ * Portions Copyright (c) 2010 Phil Sutter
+ *
+ * Author: Nikos Mavrogiannopoulos <[email protected]>
+ *
+ * This file is part of linux cryptodev.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <linux/audit.h>
+#include <linux/crypto.h>
+#include <linux/mutex.h>
+#include <linux/ncr.h>
+#include "ncr-int.h"
+#include <linux/mm_types.h>
+#include <linux/scatterlist.h>
+#include <net/netlink.h>
+
+static const struct algo_properties_st algo_properties[] = {
+#define KSTR(x) .kstr = x, .kstr_len = sizeof(x) - 1
+ { .algo = NCR_ALG_NULL, KSTR("ecb(cipher_null)"),
+ .needs_iv = 0, .is_symmetric=1, .can_encrypt=1,
+ .key_type = NCR_KEY_TYPE_INVALID },
+ { KSTR("cbc(des3_ede)"),
+ .needs_iv = 1, .is_symmetric=1, .can_encrypt=1,
+ .key_type = NCR_KEY_TYPE_SECRET },
+ { KSTR("cbc(aes)"),
+ .needs_iv = 1, .is_symmetric=1, .can_encrypt=1,
+ .key_type = NCR_KEY_TYPE_SECRET },
+ { KSTR("cbc(camelia)"),
+ .needs_iv = 1, .is_symmetric=1, .can_encrypt=1,
+ .key_type = NCR_KEY_TYPE_SECRET },
+ { KSTR("ctr(aes)"),
+ .needs_iv = 1, .is_symmetric=1, .can_encrypt=1,
+ .key_type = NCR_KEY_TYPE_SECRET },
+ { KSTR("ctr(camelia)"),
+ .needs_iv = 1, .is_symmetric=1, .can_encrypt=1,
+ .key_type = NCR_KEY_TYPE_SECRET },
+ { KSTR("ecb(aes)"),
+ .needs_iv = 0, .is_symmetric=1, .can_encrypt=1,
+ .key_type = NCR_KEY_TYPE_SECRET },
+ { KSTR("ecb(camelia)"),
+ .needs_iv = 0, .is_symmetric=1, .can_encrypt=1,
+ .key_type = NCR_KEY_TYPE_SECRET },
+ { .algo = NCR_ALG_SHA1, KSTR("sha1"),
+ .digest_size = 20, .can_digest=1,
+ .key_type = NCR_KEY_TYPE_INVALID },
+ { .algo = NCR_ALG_MD5, KSTR("md5"),
+ .digest_size = 16, .can_digest=1,
+ .key_type = NCR_KEY_TYPE_INVALID },
+ { .algo = NCR_ALG_SHA2_224, KSTR("sha224"),
+ .digest_size = 28, .can_digest=1,
+ .key_type = NCR_KEY_TYPE_INVALID },
+ { .algo = NCR_ALG_SHA2_256, KSTR("sha256"),
+ .digest_size = 32, .can_digest=1,
+ .key_type = NCR_KEY_TYPE_INVALID },
+ { .algo = NCR_ALG_SHA2_384, KSTR("sha384"),
+ .digest_size = 48, .can_digest=1,
+ .key_type = NCR_KEY_TYPE_INVALID },
+ { .algo = NCR_ALG_SHA2_512, KSTR("sha512"),
+ .digest_size = 64, .can_digest=1,
+ .key_type = NCR_KEY_TYPE_INVALID },
+ { .is_hmac = 1, KSTR("hmac(sha1)"),
+ .digest_size = 20, .can_sign=1,
+ .key_type = NCR_KEY_TYPE_SECRET },
+ { .is_hmac = 1, KSTR("hmac(md5)"),
+ .digest_size = 16, .can_sign=1,
+ .key_type = NCR_KEY_TYPE_SECRET },
+ { .is_hmac = 1, KSTR("hmac(sha224)"),
+ .digest_size = 28, .can_sign=1,
+ .key_type = NCR_KEY_TYPE_SECRET },
+ { .is_hmac = 1, KSTR("hmac(sha256)"),
+ .digest_size = 32, .can_sign=1,
+ .key_type = NCR_KEY_TYPE_SECRET },
+ { .is_hmac = 1, KSTR("hmac(sha384)"),
+ .digest_size = 48, .can_sign=1,
+ .key_type = NCR_KEY_TYPE_SECRET },
+ { .is_hmac = 1, KSTR("hmac(sha512)"),
+ .digest_size = 64, .can_sign=1,
+ .key_type = NCR_KEY_TYPE_SECRET },
+ /* NOTE: These algorithm names are not available through the kernel API
+ (yet). */
+ { .algo = NCR_ALG_RSA, KSTR("rsa"), .is_pk = 1,
+ .can_encrypt=1, .can_sign=1, .key_type = NCR_KEY_TYPE_PUBLIC },
+ { .algo = NCR_ALG_DSA, KSTR("dsa"), .is_pk = 1,
+ .can_sign=1, .key_type = NCR_KEY_TYPE_PUBLIC },
+ { .algo = NCR_ALG_DH, KSTR("dh"), .is_pk = 1,
+ .can_kx=1, .key_type = NCR_KEY_TYPE_PUBLIC },
+#undef KSTR
+};
+
+/* The lookups by string are inefficient - can we look up all we need from
+ crypto API? */
+const struct algo_properties_st *_ncr_algo_to_properties(const char *algo)
+{
+ const struct algo_properties_st *a;
+ size_t name_len;
+
+ name_len = strlen(algo);
+ for (a = algo_properties;
+ a < algo_properties + ARRAY_SIZE(algo_properties); a++) {
+ if (a->kstr_len == name_len
+ && memcmp(a->kstr, algo, name_len) == 0)
+ return a;
+ }
+
+ return NULL;
+}
+
+const struct algo_properties_st *_ncr_nla_to_properties(const struct nlattr *nla)
+{
+ const struct algo_properties_st *a;
+ size_t name_len;
+
+ if (nla == NULL)
+ return NULL;
+
+ /* nla_len() >= 1 ensured by validate_nla() case NLA_NUL_STRING */
+ name_len = nla_len(nla) - 1;
+ for (a = algo_properties;
+ a < algo_properties + ARRAY_SIZE(algo_properties); a++) {
+ if (a->kstr_len == name_len
+ && memcmp(a->kstr, nla_data(nla), name_len + 1) == 0)
+ return a;
+ }
+ return NULL;
+}
+
+const char *ncr_algorithm_name(const struct algo_properties_st *algo)
+{
+ if (algo != NULL && algo->kstr != NULL)
+ return algo->kstr;
+ return "unknown";
+}
--
1.7.2.1

2010-08-20 08:45:53

by Miloslav Trmac

[permalink] [raw]
Subject: [PATCH 10/19] Add libtomcrypt implementation

No use postponing it any more I'm afraid.

(Reviewing this in detail is probably premature, we are considering
replacing the implementation by something based on libgcrypt, which is
more actively maintained and has been probably more thorouhgly examined
for vulnerabilities.)
---
crypto/userspace/Makefile | 38 ++-
.../libtomcrypt/hashes/crypt_hash_is_valid.c | 30 ++
crypto/userspace/libtomcrypt/hashes/hash_get_oid.c | 78 ++++
crypto/userspace/libtomcrypt/hashes/hash_memory.c | 66 ++++
.../libtomcrypt/hashes/hash_memory_multi.c | 84 +++++
.../userspace/libtomcrypt/headers/tomcrypt_prng.h | 80 ++++
crypto/userspace/libtomcrypt/math/rand_prime.c | 80 ++++
.../libtomcrypt/misc/crypt/crypt_argchk.c | 28 ++
crypto/userspace/libtomcrypt/misc/pk_get_oid.c | 40 ++
crypto/userspace/libtomcrypt/misc/qsort.c | 247 ++++++++++++
crypto/userspace/libtomcrypt/misc/zeromem.c | 34 ++
.../pk/asn1/der/bit/der_decode_bit_string.c | 106 ++++++
.../pk/asn1/der/bit/der_encode_bit_string.c | 92 +++++
.../pk/asn1/der/bit/der_length_bit_string.c | 54 +++
.../pk/asn1/der/boolean/der_decode_boolean.c | 47 +++
.../pk/asn1/der/boolean/der_encode_boolean.c | 51 +++
.../pk/asn1/der/boolean/der_length_boolean.c | 35 ++
.../pk/asn1/der/choice/der_decode_choice.c | 182 +++++++++
.../pk/asn1/der/ia5/der_decode_ia5_string.c | 96 +++++
.../pk/asn1/der/ia5/der_encode_ia5_string.c | 85 +++++
.../pk/asn1/der/ia5/der_length_ia5_string.c | 194 ++++++++++
.../pk/asn1/der/integer/der_decode_integer.c | 110 ++++++
.../pk/asn1/der/integer/der_encode_integer.c | 130 +++++++
.../pk/asn1/der/integer/der_length_integer.c | 82 ++++
.../der_decode_object_identifier.c | 99 +++++
.../der_encode_object_identifier.c | 111 ++++++
.../der_length_object_identifier.c | 89 +++++
.../pk/asn1/der/octet/der_decode_octet_string.c | 91 +++++
.../pk/asn1/der/octet/der_encode_octet_string.c | 86 +++++
.../pk/asn1/der/octet/der_length_octet_string.c | 53 +++
.../printable_string/der_decode_printable_string.c | 96 +++++
.../printable_string/der_encode_printable_string.c | 85 +++++
.../printable_string/der_length_printable_string.c | 166 ++++++++
.../pk/asn1/der/sequence/der_decode_sequence_ex.c | 287 ++++++++++++++
.../asn1/der/sequence/der_decode_sequence_flexi.c | 394 ++++++++++++++++++++
.../asn1/der/sequence/der_decode_sequence_multi.c | 140 +++++++
.../pk/asn1/der/sequence/der_encode_sequence_ex.c | 335 +++++++++++++++++
.../asn1/der/sequence/der_encode_sequence_multi.c | 139 +++++++
.../pk/asn1/der/sequence/der_length_sequence.c | 169 +++++++++
.../pk/asn1/der/sequence/der_sequence_free.c | 66 ++++
.../libtomcrypt/pk/asn1/der/set/der_encode_set.c | 104 +++++
.../libtomcrypt/pk/asn1/der/set/der_encode_setof.c | 163 ++++++++
.../der/short_integer/der_decode_short_integer.c | 68 ++++
.../der/short_integer/der_encode_short_integer.c | 97 +++++
.../der/short_integer/der_length_short_integer.c | 70 ++++
.../pk/asn1/der/utctime/der_decode_utctime.c | 127 +++++++
.../pk/asn1/der/utctime/der_encode_utctime.c | 83 ++++
.../pk/asn1/der/utctime/der_length_utctime.c | 46 +++
.../pk/asn1/der/utf8/der_decode_utf8_string.c | 111 ++++++
.../pk/asn1/der/utf8/der_encode_utf8_string.c | 105 ++++++
.../pk/asn1/der/utf8/der_length_utf8_string.c | 83 ++++
.../der/x509/der_decode_subject_public_key_info.c | 112 ++++++
.../der/x509/der_encode_subject_public_key_info.c | 83 ++++
crypto/userspace/libtomcrypt/pk/dsa/dsa_export.c | 99 +++++
crypto/userspace/libtomcrypt/pk/dsa/dsa_free.c | 34 ++
crypto/userspace/libtomcrypt/pk/dsa/dsa_import.c | 101 +++++
crypto/userspace/libtomcrypt/pk/dsa/dsa_make_key.c | 125 ++++++
.../userspace/libtomcrypt/pk/dsa/dsa_sign_hash.c | 147 ++++++++
.../userspace/libtomcrypt/pk/dsa/dsa_verify_hash.c | 126 +++++++
.../userspace/libtomcrypt/pk/dsa/dsa_verify_key.c | 100 +++++
.../userspace/libtomcrypt/pk/pkcs1/pkcs_1_i2osp.c | 51 +++
.../userspace/libtomcrypt/pk/pkcs1/pkcs_1_mgf1.c | 91 +++++
.../libtomcrypt/pk/pkcs1/pkcs_1_oaep_decode.c | 192 ++++++++++
.../libtomcrypt/pk/pkcs1/pkcs_1_oaep_encode.c | 164 ++++++++
.../userspace/libtomcrypt/pk/pkcs1/pkcs_1_os2ip.c | 36 ++
.../libtomcrypt/pk/pkcs1/pkcs_1_pss_decode.c | 168 +++++++++
.../libtomcrypt/pk/pkcs1/pkcs_1_pss_encode.c | 157 ++++++++
.../libtomcrypt/pk/pkcs1/pkcs_1_v1_5_decode.c | 110 ++++++
.../libtomcrypt/pk/pkcs1/pkcs_1_v1_5_encode.c | 95 +++++
.../userspace/libtomcrypt/pk/rsa/rsa_decrypt_key.c | 107 ++++++
.../userspace/libtomcrypt/pk/rsa/rsa_encrypt_key.c | 96 +++++
crypto/userspace/libtomcrypt/pk/rsa/rsa_export.c | 87 +++++
crypto/userspace/libtomcrypt/pk/rsa/rsa_exptmod.c | 147 ++++++++
crypto/userspace/libtomcrypt/pk/rsa/rsa_free.c | 34 ++
crypto/userspace/libtomcrypt/pk/rsa/rsa_import.c | 128 +++++++
crypto/userspace/libtomcrypt/pk/rsa/rsa_make_key.c | 105 ++++++
.../userspace/libtomcrypt/pk/rsa/rsa_sign_hash.c | 130 +++++++
.../userspace/libtomcrypt/pk/rsa/rsa_verify_hash.c | 170 +++++++++
78 files changed, 8526 insertions(+), 1 deletions(-)
create mode 100644 crypto/userspace/libtomcrypt/hashes/crypt_hash_is_valid.c
create mode 100644 crypto/userspace/libtomcrypt/hashes/hash_get_oid.c
create mode 100644 crypto/userspace/libtomcrypt/hashes/hash_memory.c
create mode 100644 crypto/userspace/libtomcrypt/hashes/hash_memory_multi.c
create mode 100644 crypto/userspace/libtomcrypt/headers/tomcrypt_prng.h
create mode 100644 crypto/userspace/libtomcrypt/math/rand_prime.c
create mode 100644 crypto/userspace/libtomcrypt/misc/crypt/crypt_argchk.c
create mode 100644 crypto/userspace/libtomcrypt/misc/pk_get_oid.c
create mode 100644 crypto/userspace/libtomcrypt/misc/qsort.c
create mode 100644 crypto/userspace/libtomcrypt/misc/zeromem.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/bit/der_decode_bit_string.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/bit/der_encode_bit_string.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/bit/der_length_bit_string.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/boolean/der_decode_boolean.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/boolean/der_encode_boolean.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/boolean/der_length_boolean.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/choice/der_decode_choice.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/ia5/der_decode_ia5_string.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/ia5/der_encode_ia5_string.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/ia5/der_length_ia5_string.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/integer/der_decode_integer.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/integer/der_encode_integer.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/integer/der_length_integer.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/object_identifier/der_decode_object_identifier.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/object_identifier/der_encode_object_identifier.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/object_identifier/der_length_object_identifier.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/octet/der_decode_octet_string.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/octet/der_encode_octet_string.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/octet/der_length_octet_string.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/printable_string/der_decode_printable_string.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/printable_string/der_encode_printable_string.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/printable_string/der_length_printable_string.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_ex.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_flexi.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_multi.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_encode_sequence_ex.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_encode_sequence_multi.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_length_sequence.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_sequence_free.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/set/der_encode_set.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/set/der_encode_setof.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/short_integer/der_decode_short_integer.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/short_integer/der_encode_short_integer.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/short_integer/der_length_short_integer.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/utctime/der_decode_utctime.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/utctime/der_encode_utctime.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/utctime/der_length_utctime.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/utf8/der_decode_utf8_string.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/utf8/der_encode_utf8_string.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/utf8/der_length_utf8_string.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/x509/der_decode_subject_public_key_info.c
create mode 100644 crypto/userspace/libtomcrypt/pk/asn1/der/x509/der_encode_subject_public_key_info.c
create mode 100644 crypto/userspace/libtomcrypt/pk/dsa/dsa_export.c
create mode 100644 crypto/userspace/libtomcrypt/pk/dsa/dsa_free.c
create mode 100644 crypto/userspace/libtomcrypt/pk/dsa/dsa_import.c
create mode 100644 crypto/userspace/libtomcrypt/pk/dsa/dsa_make_key.c
create mode 100644 crypto/userspace/libtomcrypt/pk/dsa/dsa_sign_hash.c
create mode 100644 crypto/userspace/libtomcrypt/pk/dsa/dsa_verify_hash.c
create mode 100644 crypto/userspace/libtomcrypt/pk/dsa/dsa_verify_key.c
create mode 100644 crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_i2osp.c
create mode 100644 crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_mgf1.c
create mode 100644 crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_oaep_decode.c
create mode 100644 crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_oaep_encode.c
create mode 100644 crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_os2ip.c
create mode 100644 crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_pss_decode.c
create mode 100644 crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_pss_encode.c
create mode 100644 crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_v1_5_decode.c
create mode 100644 crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_v1_5_encode.c
create mode 100644 crypto/userspace/libtomcrypt/pk/rsa/rsa_decrypt_key.c
create mode 100644 crypto/userspace/libtomcrypt/pk/rsa/rsa_encrypt_key.c
create mode 100644 crypto/userspace/libtomcrypt/pk/rsa/rsa_export.c
create mode 100644 crypto/userspace/libtomcrypt/pk/rsa/rsa_exptmod.c
create mode 100644 crypto/userspace/libtomcrypt/pk/rsa/rsa_free.c
create mode 100644 crypto/userspace/libtomcrypt/pk/rsa/rsa_import.c
create mode 100644 crypto/userspace/libtomcrypt/pk/rsa/rsa_make_key.c
create mode 100644 crypto/userspace/libtomcrypt/pk/rsa/rsa_sign_hash.c
create mode 100644 crypto/userspace/libtomcrypt/pk/rsa/rsa_verify_hash.c

diff --git a/crypto/userspace/Makefile b/crypto/userspace/Makefile
index 60a9b31..81e4122 100644
--- a/crypto/userspace/Makefile
+++ b/crypto/userspace/Makefile
@@ -28,8 +28,44 @@ TOMMATH_OBJECTS = libtommath/bncore.o libtommath/bn_mp_init.o libtommath/bn_mp_c
libtommath/bn_mp_init_set_int.o libtommath/bn_mp_invmod_slow.o libtommath/bn_mp_prime_rabin_miller_trials.o \
libtommath/bn_mp_to_signed_bin_n.o libtommath/bn_mp_to_unsigned_bin_n.o

+TOMCRYPT_OBJECTS = libtomcrypt/misc/zeromem.o libtomcrypt/misc/crypt/crypt_argchk.o \
+ libtomcrypt/math/rand_prime.o libtomcrypt/misc/qsort.o libtomcrypt/hashes/hash_get_oid.o \
+ libtomcrypt/hashes/crypt_hash_is_valid.o libtomcrypt/hashes/hash_memory.o libtomcrypt/hashes/hash_memory_multi.o \
+ libtomcrypt/pk/dsa/dsa_make_key.o libtomcrypt/pk/dsa/dsa_export.o libtomcrypt/pk/dsa/dsa_import.o \
+ libtomcrypt/pk/dsa/dsa_free.o libtomcrypt/pk/dsa/dsa_sign_hash.o libtomcrypt/pk/dsa/dsa_verify_hash.o \
+ libtomcrypt/pk/dsa/dsa_verify_key.o \
+ libtomcrypt/pk/asn1/der/bit/der_decode_bit_string.o libtomcrypt/pk/asn1/der/bit/der_encode_bit_string.o \
+ libtomcrypt/pk/asn1/der/bit/der_length_bit_string.o libtomcrypt/pk/asn1/der/boolean/der_decode_boolean.o \
+ libtomcrypt/pk/asn1/der/boolean/der_encode_boolean.o libtomcrypt/pk/asn1/der/boolean/der_length_boolean.o \
+ libtomcrypt/pk/asn1/der/choice/der_decode_choice.o libtomcrypt/pk/asn1/der/ia5/der_decode_ia5_string.o \
+ libtomcrypt/pk/asn1/der/ia5/der_encode_ia5_string.o libtomcrypt/pk/asn1/der/ia5/der_length_ia5_string.o \
+ libtomcrypt/pk/asn1/der/integer/der_decode_integer.o libtomcrypt/pk/asn1/der/integer/der_encode_integer.o \
+ libtomcrypt/pk/asn1/der/integer/der_length_integer.o libtomcrypt/pk/asn1/der/object_identifier/der_decode_object_identifier.o \
+ libtomcrypt/pk/asn1/der/object_identifier/der_encode_object_identifier.o libtomcrypt/pk/asn1/der/object_identifier/der_length_object_identifier.o \
+ libtomcrypt/pk/asn1/der/octet/der_decode_octet_string.o libtomcrypt/pk/asn1/der/octet/der_encode_octet_string.o \
+ libtomcrypt/pk/asn1/der/octet/der_length_octet_string.o libtomcrypt/pk/asn1/der/printable_string/der_decode_printable_string.o \
+ libtomcrypt/pk/asn1/der/printable_string/der_encode_printable_string.o libtomcrypt/pk/asn1/der/printable_string/der_length_printable_string.o \
+ libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_ex.o libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_flexi.o \
+ libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_multi.o libtomcrypt/pk/asn1/der/sequence/der_encode_sequence_ex.o \
+ libtomcrypt/pk/asn1/der/sequence/der_encode_sequence_multi.o libtomcrypt/pk/asn1/der/sequence/der_length_sequence.o \
+ libtomcrypt/pk/asn1/der/sequence/der_sequence_free.o libtomcrypt/pk/asn1/der/short_integer/der_decode_short_integer.o \
+ libtomcrypt/pk/asn1/der/short_integer/der_encode_short_integer.o libtomcrypt/pk/asn1/der/short_integer/der_length_short_integer.o \
+ libtomcrypt/pk/asn1/der/utctime/der_decode_utctime.o libtomcrypt/pk/asn1/der/utctime/der_encode_utctime.o \
+ libtomcrypt/pk/asn1/der/utctime/der_length_utctime.o libtomcrypt/pk/asn1/der/utf8/der_decode_utf8_string.o \
+ libtomcrypt/pk/asn1/der/utf8/der_encode_utf8_string.o libtomcrypt/pk/asn1/der/utf8/der_length_utf8_string.o \
+ libtomcrypt/pk/asn1/der/set/der_encode_set.o libtomcrypt/pk/asn1/der/set/der_encode_setof.o \
+ libtomcrypt/pk/rsa/rsa_decrypt_key.o libtomcrypt/pk/rsa/rsa_encrypt_key.o libtomcrypt/pk/rsa/rsa_export.o \
+ libtomcrypt/pk/rsa/rsa_exptmod.o libtomcrypt/pk/rsa/rsa_free.o libtomcrypt/pk/rsa/rsa_import.o \
+ libtomcrypt/pk/rsa/rsa_make_key.o libtomcrypt/pk/rsa/rsa_sign_hash.o libtomcrypt/pk/rsa/rsa_verify_hash.o \
+ libtomcrypt/pk/pkcs1/pkcs_1_i2osp.o libtomcrypt/pk/pkcs1/pkcs_1_mgf1.o libtomcrypt/pk/pkcs1/pkcs_1_oaep_decode.o \
+ libtomcrypt/pk/pkcs1/pkcs_1_oaep_encode.o libtomcrypt/pk/pkcs1/pkcs_1_os2ip.o libtomcrypt/pk/pkcs1/pkcs_1_pss_decode.o \
+ libtomcrypt/pk/pkcs1/pkcs_1_pss_encode.o libtomcrypt/pk/pkcs1/pkcs_1_v1_5_decode.o libtomcrypt/pk/pkcs1/pkcs_1_v1_5_encode.o \
+ libtomcrypt/misc/pk_get_oid.o libtomcrypt/pk/asn1/der/x509/der_encode_subject_public_key_info.o \
+ libtomcrypt/pk/asn1/der/x509/der_decode_subject_public_key_info.o
+
cryptodev-objs := cryptodev_main.o cryptodev_cipher.o ncr-limits.o \
- utils.o $(TOMMATH_OBJECTS)
+ utils.o $(TOMMATH_OBJECTS) \
+ $(TOMCRYPT_OBJECTS)


obj-$(CONFIG_CRYPTO_USERSPACE) += cryptodev.o
diff --git a/crypto/userspace/libtomcrypt/hashes/crypt_hash_is_valid.c b/crypto/userspace/libtomcrypt/hashes/crypt_hash_is_valid.c
new file mode 100644
index 0000000..d01d418
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/hashes/crypt_hash_is_valid.c
@@ -0,0 +1,30 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file crypt_hash_is_valid.c
+ Determine if hash is valid, Tom St Denis
+*/
+
+/*
+ Test if a hash index is valid
+ @param idx The hash to search for
+ @return CRYPT_OK if valid
+*/
+int hash_is_valid(const struct algo_properties_st *hash)
+{
+ return CRYPT_OK;
+}
+
+/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_hash_is_valid.c,v $ */
+/* $Revision: 1.6 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/hashes/hash_get_oid.c b/crypto/userspace/libtomcrypt/hashes/hash_get_oid.c
new file mode 100644
index 0000000..39f4372
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/hashes/hash_get_oid.c
@@ -0,0 +1,78 @@
+/* LibTomCrypt, modular cryptographic library
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ */
+#include "tomcrypt.h"
+#include <ncr-int.h>
+
+/*
+ Returns the OID of the hash.
+ @param idx The hash identifier of the hash to search for
+ @return CRYPT_OK if valid
+*/
+
+static const oid_st sha1_oid = {
+ .OIDlen = 6,
+ .OID = { 1, 3, 14, 3, 2, 26 },
+};
+
+static const oid_st md5_oid = {
+ .OIDlen = 6,
+ .OID = { 1, 2, 840, 113549, 2, 5, },
+};
+
+static const oid_st sha224_oid = {
+ .OIDlen = 9,
+ .OID = { 2, 16, 840, 1, 101, 3, 4, 2, 4, },
+};
+
+static const oid_st sha256_oid = {
+ .OIDlen = 9,
+ .OID = { 2, 16, 840, 1, 101, 3, 4, 2, 1, },
+};
+
+static const oid_st sha384_oid = {
+ .OIDlen = 9,
+ .OID = { 2, 16, 840, 1, 101, 3, 4, 2, 2, },
+};
+
+static const oid_st sha512_oid = {
+ .OIDlen = 9,
+ .OID = { 2, 16, 840, 1, 101, 3, 4, 2, 3, },
+};
+
+int hash_get_oid(const struct algo_properties_st *hash, oid_st *st)
+{
+ switch (hash->algo) {
+ case NCR_ALG_SHA1:
+ memcpy(st, &sha1_oid, sizeof(*st));
+ break;
+ case NCR_ALG_MD5:
+ memcpy(st, &md5_oid, sizeof(*st));
+ break;
+ case NCR_ALG_SHA2_224:
+ memcpy(st, &sha224_oid, sizeof(*st));
+ break;
+ case NCR_ALG_SHA2_256:
+ memcpy(st, &sha256_oid, sizeof(*st));
+ break;
+ case NCR_ALG_SHA2_384:
+ memcpy(st, &sha384_oid, sizeof(*st));
+ break;
+ case NCR_ALG_SHA2_512:
+ memcpy(st, &sha512_oid, sizeof(*st));
+ break;
+ default:
+ return CRYPT_INVALID_ARG;
+ }
+ return CRYPT_OK;
+}
+
+/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_hash_is_valid.c,v $ */
+/* $Revision: 1.6 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/hashes/hash_memory.c b/crypto/userspace/libtomcrypt/hashes/hash_memory.c
new file mode 100644
index 0000000..a416de9
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/hashes/hash_memory.c
@@ -0,0 +1,66 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include <ncr-int.h>
+#include <cryptodev_int.h>
+
+/**
+ @file hash_memory.c
+ Hash memory helper, Tom St Denis
+*/
+
+/**
+ Hash a block of memory and store the digest.
+ @param hash The hash you wish to use
+ @param in The data you wish to hash
+ @param inlen The length of the data to hash (octets)
+ @param out [out] Where to store the digest
+ @param outlen [in/out] Max size and resulting size of the digest
+ @return CRYPT_OK if successful
+*/
+int hash_memory(const struct algo_properties_st *hash, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen)
+{
+ int err;
+ struct hash_data hdata;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ if ((err = hash_is_valid(hash)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (*outlen < hash->digest_size) {
+ *outlen = hash->digest_size;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ err = cryptodev_hash_init( &hdata, hash->kstr, 0, NULL, 0);
+ if (err < 0) {
+ err = CRYPT_INVALID_HASH;
+ goto LBL_ERR;
+ }
+
+ if ((err = _cryptodev_hash_update(&hdata, in, inlen)) < 0) {
+ err = CRYPT_ERROR;
+ goto LBL_ERR;
+ }
+
+ err = cryptodev_hash_final(&hdata, out);
+
+ *outlen = hash->digest_size;
+LBL_ERR:
+ cryptodev_hash_deinit(&hdata);
+
+ return err;
+}
+
diff --git a/crypto/userspace/libtomcrypt/hashes/hash_memory_multi.c b/crypto/userspace/libtomcrypt/hashes/hash_memory_multi.c
new file mode 100644
index 0000000..a914916
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/hashes/hash_memory_multi.c
@@ -0,0 +1,84 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include <stdarg.h>
+#include <ncr-int.h>
+#include <cryptodev_int.h>
+
+/**
+ @file hash_memory_multi.c
+ Hash (multiple buffers) memory helper, Tom St Denis
+*/
+
+/**
+ Hash multiple (non-adjacent) blocks of memory at once.
+ @param hash The hash you wish to use
+ @param out [out] Where to store the digest
+ @param outlen [in/out] Max size and resulting size of the digest
+ @param in The data you wish to hash
+ @param inlen The length of the data to hash (octets)
+ @param ... tuples of (data,len) pairs to hash, terminated with a (NULL,x) (x=don't care)
+ @return CRYPT_OK if successful
+*/
+int hash_memory_multi(const struct algo_properties_st *hash, unsigned char *out, unsigned long *outlen,
+ const unsigned char *in, unsigned long inlen, ...)
+{
+ struct hash_data hdata;
+ int err;
+ va_list args;
+ const unsigned char *curptr;
+ unsigned long curlen;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ if ((err = hash_is_valid(hash)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (*outlen < hash->digest_size) {
+ *outlen = hash->digest_size;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ err = cryptodev_hash_init( &hdata, hash->kstr, 0, NULL, 0);
+ if (err < 0) {
+ err = CRYPT_INVALID_HASH;
+ goto LBL_ERR;
+ }
+
+ va_start(args, inlen);
+ curptr = in;
+ curlen = inlen;
+ for (;;) {
+ /* process buf */
+ if ((err = _cryptodev_hash_update(&hdata, curptr, curlen)) < 0) {
+ err = CRYPT_ERROR;
+ goto LBL_ERR;
+ }
+ /* step to next */
+ curptr = va_arg(args, const unsigned char*);
+ if (curptr == NULL) {
+ break;
+ }
+ curlen = va_arg(args, unsigned long);
+ }
+
+ err = cryptodev_hash_final(&hdata, out);
+
+ *outlen = hash->digest_size;
+LBL_ERR:
+ cryptodev_hash_deinit(&hdata);
+ va_end(args);
+ return err;
+}
+
diff --git a/crypto/userspace/libtomcrypt/headers/tomcrypt_prng.h b/crypto/userspace/libtomcrypt/headers/tomcrypt_prng.h
new file mode 100644
index 0000000..26bf711
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/headers/tomcrypt_prng.h
@@ -0,0 +1,80 @@
+/* ---- PRNG Stuff ---- */
+
+typedef union Prng_state {
+ char dummy[1];
+} prng_state;
+
+/** PRNG descriptor */
+extern struct ltc_prng_descriptor {
+ /** Name of the PRNG */
+ char *name;
+ /** size in bytes of exported state */
+ int export_size;
+ /** Start a PRNG state
+ @param prng [out] The state to initialize
+ @return CRYPT_OK if successful
+ */
+ int (*start)(prng_state *prng);
+ /** Add entropy to the PRNG
+ @param in The entropy
+ @param inlen Length of the entropy (octets)\
+ @param prng The PRNG state
+ @return CRYPT_OK if successful
+ */
+ int (*add_entropy)(const unsigned char *in, unsigned long inlen, prng_state *prng);
+ /** Ready a PRNG state to read from
+ @param prng The PRNG state to ready
+ @return CRYPT_OK if successful
+ */
+ int (*ready)(prng_state *prng);
+ /** Read from the PRNG
+ @param out [out] Where to store the data
+ @param outlen Length of data desired (octets)
+ @param prng The PRNG state to read from
+ @return Number of octets read
+ */
+ unsigned long (*read)(unsigned char *out, unsigned long outlen, prng_state *prng);
+ /** Terminate a PRNG state
+ @param prng The PRNG state to terminate
+ @return CRYPT_OK if successful
+ */
+ int (*done)(prng_state *prng);
+ /** Export a PRNG state
+ @param out [out] The destination for the state
+ @param outlen [in/out] The max size and resulting size of the PRNG state
+ @param prng The PRNG to export
+ @return CRYPT_OK if successful
+ */
+ int (*pexport)(unsigned char *out, unsigned long *outlen, prng_state *prng);
+ /** Import a PRNG state
+ @param in The data to import
+ @param inlen The length of the data to import (octets)
+ @param prng The PRNG to initialize/import
+ @return CRYPT_OK if successful
+ */
+ int (*pimport)(const unsigned char *in, unsigned long inlen, prng_state *prng);
+ /** Self-test the PRNG
+ @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled
+ */
+ int (*test)(void);
+} prng_descriptor[];
+
+int linux_start(prng_state *prng);
+int linux_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng);
+int linux_ready(prng_state *prng);
+unsigned long linux_read(unsigned char *out, unsigned long outlen, prng_state *prng);
+int linux_done(prng_state *prng);
+int linux_export(unsigned char *out, unsigned long *outlen, prng_state *prng);
+int linux_import(const unsigned char *in, unsigned long inlen, prng_state *prng);
+int linux_test(void);
+
+extern const struct ltc_prng_descriptor linux_desc;
+
+int find_prng(const char *name);
+int register_prng(const struct ltc_prng_descriptor *prng);
+int unregister_prng(const struct ltc_prng_descriptor *prng);
+int prng_is_valid(int idx);
+
+/* $Source: /cvs/libtom/libtomcrypt/src/headers/tomcrypt_prng.h,v $ */
+/* $Revision: 1.9 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/math/rand_prime.c b/crypto/userspace/libtomcrypt/math/rand_prime.c
new file mode 100644
index 0000000..ab73cd0
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/math/rand_prime.c
@@ -0,0 +1,80 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include <linux/slab.h>
+
+/**
+ @file rand_prime.c
+ Generate a random prime, Tom St Denis
+*/
+
+#define USE_BBS 1
+
+int rand_prime(mp_int *N, long len)
+{
+ int err, res, type;
+ unsigned char *buf;
+
+ LTC_ARGCHK(N != NULL);
+
+ /* get type */
+ if (len < 0) {
+ type = USE_BBS;
+ len = -len;
+ } else {
+ type = 0;
+ }
+
+ /* allow sizes between 2 and 512 bytes for a prime size */
+ if (len < 2 || len > 512) {
+ return CRYPT_INVALID_PRIME_SIZE;
+ }
+
+ /* allocate buffer to work with */
+ buf = XCALLOC(1, len);
+ if (buf == NULL) {
+ return CRYPT_MEM;
+ }
+
+ do {
+ /* generate value */
+ get_random_bytes( buf, len);
+
+ /* munge bits */
+ buf[0] |= 0x80 | 0x40;
+ buf[len-1] |= 0x01 | ((type & USE_BBS) ? 0x02 : 0x00);
+
+ /* load value */
+ if ((err = mp_read_unsigned_bin(N, buf, len)) != CRYPT_OK) {
+ XFREE(buf);
+ return err;
+ }
+
+ /* test */
+ if ((err = mp_prime_is_prime(N, 8, &res)) != CRYPT_OK) {
+ XFREE(buf);
+ return err;
+ }
+ } while (res == LTC_MP_NO);
+
+#ifdef LTC_CLEAN_STACK
+ zeromem(buf, len);
+#endif
+
+ XFREE(buf);
+ return CRYPT_OK;
+}
+
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/math/rand_prime.c,v $ */
+/* $Revision: 1.7 $ */
+/* $Date: 2006/12/28 01:27:23 $ */
diff --git a/crypto/userspace/libtomcrypt/misc/crypt/crypt_argchk.c b/crypto/userspace/libtomcrypt/misc/crypt/crypt_argchk.c
new file mode 100644
index 0000000..143b784
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/misc/crypt/crypt_argchk.c
@@ -0,0 +1,28 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file crypt_argchk.c
+ Perform argument checking, Tom St Denis
+*/
+
+#if (ARGTYPE == 0)
+void crypt_argchk(char *v, char *s, int d)
+{
+ printk("LTC_ARGCHK '%s' failure on line %d of file %s\n",
+ v, d, s);
+}
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/misc/crypt/crypt_argchk.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/misc/pk_get_oid.c b/crypto/userspace/libtomcrypt/misc/pk_get_oid.c
new file mode 100644
index 0000000..197d7ae
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/misc/pk_get_oid.c
@@ -0,0 +1,40 @@
+/* LibTomCrypt, modular cryptographic library
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ */
+#include "tomcrypt.h"
+
+static const oid_st rsa_oid = {
+ .OIDlen = 7,
+ .OID = { 1, 2, 840, 113549, 1, 1, 1 },
+};
+
+static const oid_st dsa_oid = {
+ .OIDlen = 6,
+ .OID = { 1, 2, 840, 10040, 4, 1 },
+};
+
+/*
+ Returns the OID of the public key algorithm.
+ @return CRYPT_OK if valid
+*/
+int pk_get_oid(int pk, oid_st *st)
+{
+ switch (pk) {
+ case PKA_RSA:
+ memcpy(st, &rsa_oid, sizeof(*st));
+ break;
+ case PKA_DSA:
+ memcpy(st, &dsa_oid, sizeof(*st));
+ break;
+ default:
+ return CRYPT_INVALID_ARG;
+ }
+ return CRYPT_OK;
+}
+
diff --git a/crypto/userspace/libtomcrypt/misc/qsort.c b/crypto/userspace/libtomcrypt/misc/qsort.c
new file mode 100644
index 0000000..72f5108
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/misc/qsort.c
@@ -0,0 +1,247 @@
+/* Copyright (C) 1991,1992,1996,1997,1999,2004 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Douglas C. Schmidt ([email protected]).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+/* If you consider tuning this algorithm, you should consult first:
+ Engineering a sort function; Jon Bentley and M. Douglas McIlroy;
+ Software - Practice and Experience; Vol. 23 (11), 1249-1265, 1993. */
+
+#include <tomcrypt.h>
+
+/* Byte-wise swap two items of size SIZE. */
+#define SWAP(a, b, size) \
+ do \
+ { \
+ register size_t __size = (size); \
+ register char *__a = (a), *__b = (b); \
+ do \
+ { \
+ char __tmp = *__a; \
+ *__a++ = *__b; \
+ *__b++ = __tmp; \
+ } while (--__size > 0); \
+ } while (0)
+
+/* Discontinue quicksort algorithm when partition gets below this size.
+ This particular magic number was chosen to work best on a Sun 4/260. */
+#define MAX_THRESH 4
+
+/* Stack node declarations used to store unfulfilled partition obligations. */
+typedef struct
+ {
+ char *lo;
+ char *hi;
+ } stack_node;
+
+/* The next 4 #defines implement a very fast in-line stack abstraction. */
+/* The stack needs log (total_elements) entries (we could even subtract
+ log(MAX_THRESH)). Since total_elements has type size_t, we get as
+ upper bound for log (total_elements):
+ bits per byte (CHAR_BIT) * sizeof(size_t). */
+#define STACK_SIZE (CHAR_BIT * sizeof(size_t))
+#define PUSH(low, high) ((void) ((top->lo = (low)), (top->hi = (high)), ++top))
+#define POP(low, high) ((void) (--top, (low = top->lo), (high = top->hi)))
+#define STACK_NOT_EMPTY (stack < top)
+
+
+/* Order size using quicksort. This implementation incorporates
+ four optimizations discussed in Sedgewick:
+
+ 1. Non-recursive, using an explicit stack of pointer that store the
+ next array partition to sort. To save time, this maximum amount
+ of space required to store an array of SIZE_MAX is allocated on the
+ stack. Assuming a 32-bit (64 bit) integer for size_t, this needs
+ only 32 * sizeof(stack_node) == 256 bytes (for 64 bit: 1024 bytes).
+ Pretty cheap, actually.
+
+ 2. Chose the pivot element using a median-of-three decision tree.
+ This reduces the probability of selecting a bad pivot value and
+ eliminates certain extraneous comparisons.
+
+ 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving
+ insertion sort to order the MAX_THRESH items within each partition.
+ This is a big win, since insertion sort is faster for small, mostly
+ sorted array segments.
+
+ 4. The larger of the two sub-partitions is always pushed onto the
+ stack first, with the algorithm then concentrating on the
+ smaller partition. This *guarantees* no more than log (total_elems)
+ stack size is needed (actually O(1) in this case)! */
+
+typedef int(*__compar_fn_t)(const void *, const void *);
+
+void
+qsort (void *const pbase, size_t total_elems, size_t size,
+ __compar_fn_t cmp)
+{
+ register char *base_ptr = (char *) pbase;
+
+ const size_t max_thresh = MAX_THRESH * size;
+
+ if (total_elems == 0)
+ /* Avoid lossage with unsigned arithmetic below. */
+ return;
+
+ if (total_elems > MAX_THRESH)
+ {
+ char *lo = base_ptr;
+ char *hi = &lo[size * (total_elems - 1)];
+ stack_node stack[STACK_SIZE];
+ stack_node *top = stack;
+
+ PUSH (NULL, NULL);
+
+ while (STACK_NOT_EMPTY)
+ {
+ char *left_ptr;
+ char *right_ptr;
+
+ /* Select median value from among LO, MID, and HI. Rearrange
+ LO and HI so the three values are sorted. This lowers the
+ probability of picking a pathological pivot value and
+ skips a comparison for both the LEFT_PTR and RIGHT_PTR in
+ the while loops. */
+
+ char *mid = lo + size * ((hi - lo) / size >> 1);
+
+ if ((*cmp) ((void *) mid, (void *) lo) < 0)
+ SWAP (mid, lo, size);
+ if ((*cmp) ((void *) hi, (void *) mid) < 0)
+ SWAP (mid, hi, size);
+ else
+ goto jump_over;
+ if ((*cmp) ((void *) mid, (void *) lo) < 0)
+ SWAP (mid, lo, size);
+ jump_over:;
+
+ left_ptr = lo + size;
+ right_ptr = hi - size;
+
+ /* Here's the famous ``collapse the walls'' section of quicksort.
+ Gotta like those tight inner loops! They are the main reason
+ that this algorithm runs much faster than others. */
+ do
+ {
+ while ((*cmp) ((void *) left_ptr, (void *) mid) < 0)
+ left_ptr += size;
+
+ while ((*cmp) ((void *) mid, (void *) right_ptr) < 0)
+ right_ptr -= size;
+
+ if (left_ptr < right_ptr)
+ {
+ SWAP (left_ptr, right_ptr, size);
+ if (mid == left_ptr)
+ mid = right_ptr;
+ else if (mid == right_ptr)
+ mid = left_ptr;
+ left_ptr += size;
+ right_ptr -= size;
+ }
+ else if (left_ptr == right_ptr)
+ {
+ left_ptr += size;
+ right_ptr -= size;
+ break;
+ }
+ }
+ while (left_ptr <= right_ptr);
+
+ /* Set up pointers for next iteration. First determine whether
+ left and right partitions are below the threshold size. If so,
+ ignore one or both. Otherwise, push the larger partition's
+ bounds on the stack and continue sorting the smaller one. */
+
+ if ((size_t) (right_ptr - lo) <= max_thresh)
+ {
+ if ((size_t) (hi - left_ptr) <= max_thresh)
+ /* Ignore both small partitions. */
+ POP (lo, hi);
+ else
+ /* Ignore small left partition. */
+ lo = left_ptr;
+ }
+ else if ((size_t) (hi - left_ptr) <= max_thresh)
+ /* Ignore small right partition. */
+ hi = right_ptr;
+ else if ((right_ptr - lo) > (hi - left_ptr))
+ {
+ /* Push larger left partition indices. */
+ PUSH (lo, right_ptr);
+ lo = left_ptr;
+ }
+ else
+ {
+ /* Push larger right partition indices. */
+ PUSH (left_ptr, hi);
+ hi = right_ptr;
+ }
+ }
+ }
+
+ /* Once the BASE_PTR array is partially sorted by quicksort the rest
+ is completely sorted using insertion sort, since this is efficient
+ for partitions below MAX_THRESH size. BASE_PTR points to the beginning
+ of the array to sort, and END_PTR points at the very last element in
+ the array (*not* one beyond it!). */
+
+ {
+ char *const end_ptr = &base_ptr[size * (total_elems - 1)];
+ char *tmp_ptr = base_ptr;
+ char *thresh = min(end_ptr, base_ptr + max_thresh);
+ register char *run_ptr;
+
+ /* Find smallest element in first threshold and place it at the
+ array's beginning. This is the smallest array element,
+ and the operation speeds up insertion sort's inner loop. */
+
+ for (run_ptr = tmp_ptr + size; run_ptr <= thresh; run_ptr += size)
+ if ((*cmp) ((void *) run_ptr, (void *) tmp_ptr) < 0)
+ tmp_ptr = run_ptr;
+
+ if (tmp_ptr != base_ptr)
+ SWAP (tmp_ptr, base_ptr, size);
+
+ /* Insertion sort, running from left-hand-side up to right-hand-side. */
+
+ run_ptr = base_ptr + size;
+ while ((run_ptr += size) <= end_ptr)
+ {
+ tmp_ptr = run_ptr - size;
+ while ((*cmp) ((void *) run_ptr, (void *) tmp_ptr) < 0)
+ tmp_ptr -= size;
+
+ tmp_ptr += size;
+ if (tmp_ptr != run_ptr)
+ {
+ char *trav;
+
+ trav = run_ptr + size;
+ while (--trav >= run_ptr)
+ {
+ char c = *trav;
+ char *hi, *lo;
+
+ for (hi = lo = trav; (lo -= size) >= tmp_ptr; hi = lo)
+ *hi = *lo;
+ *hi = c;
+ }
+ }
+ }
+ }
+}
diff --git a/crypto/userspace/libtomcrypt/misc/zeromem.c b/crypto/userspace/libtomcrypt/misc/zeromem.c
new file mode 100644
index 0000000..a4bb124
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/misc/zeromem.c
@@ -0,0 +1,34 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file zeromem.c
+ Zero a block of memory, Tom St Denis
+*/
+
+/**
+ Zero a block of memory
+ @param out The destination of the area to zero
+ @param outlen The length of the area to zero (octets)
+*/
+void zeromem(void *out, size_t outlen)
+{
+ unsigned char *mem = out;
+ LTC_ARGCHKVD(out != NULL);
+ while (outlen-- > 0) {
+ *mem++ = 0;
+ }
+}
+
+/* $Source: /cvs/libtom/libtomcrypt/src/misc/zeromem.c,v $ */
+/* $Revision: 1.7 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/bit/der_decode_bit_string.c b/crypto/userspace/libtomcrypt/pk/asn1/der/bit/der_decode_bit_string.c
new file mode 100644
index 0000000..c9f6368
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/bit/der_decode_bit_string.c
@@ -0,0 +1,106 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_decode_bit_string.c
+ ASN.1 DER, encode a BIT STRING, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+#define setbit(v, n) (v=((unsigned char)(v) | (1U << (unsigned char)(n))))
+
+/**
+ Store a BIT STRING
+ @param in The DER encoded BIT STRING
+ @param inlen The size of the DER BIT STRING
+ @param out [out] The array of bits stored (8 per char)
+ @param outlen [in/out] The number of bits stored
+ @return CRYPT_OK if successful
+*/
+int der_decode_bit_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long dlen, blen, x, y;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* packet must be at least 4 bytes */
+ if (inlen < 4) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* check for 0x03 */
+ if ((in[0]&0x1F) != 0x03) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* offset in the data */
+ x = 1;
+
+ /* get the length of the data */
+ if (in[x] & 0x80) {
+ /* long format get number of length bytes */
+ y = in[x++] & 0x7F;
+
+ /* invalid if 0 or > 2 */
+ if (y == 0 || y > 2) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* read the data len */
+ dlen = 0;
+ while (y--) {
+ dlen = (dlen << 8) | (unsigned long)in[x++];
+ }
+ } else {
+ /* short format */
+ dlen = in[x++] & 0x7F;
+ }
+
+ /* is the data len too long or too short? */
+ if ((dlen == 0) || (dlen + x > inlen)) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* get padding count */
+ blen = ((dlen - 1) << 3) - (in[x++] & 7);
+
+ /* too many bits? */
+ if (blen > *outlen) {
+ *outlen = blen;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* decode/store the bits */
+ for (y = 0; y < blen; y++) {
+ if (in[x] & (1 << (7 - (y & 7)))) {
+ setbit(out[y/8], 7-(y%8));
+ }
+ if ((y & 7) == 7) {
+ ++x;
+ }
+ }
+
+ /* we done */
+ *outlen = blen;
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/bit/der_decode_bit_string.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/bit/der_encode_bit_string.c b/crypto/userspace/libtomcrypt/pk/asn1/der/bit/der_encode_bit_string.c
new file mode 100644
index 0000000..d1b6064
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/bit/der_encode_bit_string.c
@@ -0,0 +1,92 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_encode_bit_string.c
+ ASN.1 DER, encode a BIT STRING, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+#define getbit(n, k) (((n) & ( 1 << (k) )) >> (k))
+
+/**
+ Store a BIT STRING
+ @param in The array of bits to store (8 per char)
+ @param inlen The number of bits tostore
+ @param out [out] The destination for the DER encoded BIT STRING
+ @param outlen [in/out] The max size and resulting size of the DER BIT STRING
+ @return CRYPT_OK if successful
+*/
+int der_encode_bit_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long len, x, y;
+ unsigned char buf;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* avoid overflows */
+ if ((err = der_length_bit_string(inlen, &len)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (len > *outlen) {
+ *outlen = len;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* store header (include bit padding count in length) */
+ x = 0;
+ y = (inlen >> 3) + ((inlen&7) ? 1 : 0) + 1;
+
+ out[x++] = 0x03;
+ if (y < 128) {
+ out[x++] = (unsigned char)y;
+ } else if (y < 256) {
+ out[x++] = 0x81;
+ out[x++] = (unsigned char)y;
+ } else if (y < 65536) {
+ out[x++] = 0x82;
+ out[x++] = (unsigned char)((y>>8)&255);
+ out[x++] = (unsigned char)(y&255);
+ }
+
+ /* store number of zero padding bits */
+ out[x++] = (unsigned char)((8 - inlen) & 7);
+
+ /* store the bits in big endian format */
+ for (y = buf = 0; y < inlen; y++) {
+ buf |= (getbit(in[y/8],7-y%8)?1:0) << (7 - (y & 7));
+ if ((y & 7) == 7) {
+ out[x++] = buf;
+ buf = 0;
+ }
+ }
+ /* store last byte */
+ if (inlen & 7) {
+ out[x++] = buf;
+ }
+
+ *outlen = x;
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/bit/der_encode_bit_string.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/bit/der_length_bit_string.c b/crypto/userspace/libtomcrypt/pk/asn1/der/bit/der_length_bit_string.c
new file mode 100644
index 0000000..3b7a8e1
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/bit/der_length_bit_string.c
@@ -0,0 +1,54 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_length_bit_string.c
+ ASN.1 DER, get length of BIT STRING, Tom St Denis
+*/
+
+#ifdef LTC_DER
+/**
+ Gets length of DER encoding of BIT STRING
+ @param nbits The number of bits in the string to encode
+ @param outlen [out] The length of the DER encoding for the given string
+ @return CRYPT_OK if successful
+*/
+int der_length_bit_string(unsigned long nbits, unsigned long *outlen)
+{
+ unsigned long nbytes;
+ LTC_ARGCHK(outlen != NULL);
+
+ /* get the number of the bytes */
+ nbytes = (nbits >> 3) + ((nbits & 7) ? 1 : 0) + 1;
+
+ if (nbytes < 128) {
+ /* 03 LL PP DD DD DD ... */
+ *outlen = 2 + nbytes;
+ } else if (nbytes < 256) {
+ /* 03 81 LL PP DD DD DD ... */
+ *outlen = 3 + nbytes;
+ } else if (nbytes < 65536) {
+ /* 03 82 LL LL PP DD DD DD ... */
+ *outlen = 4 + nbytes;
+ } else {
+ return CRYPT_INVALID_ARG;
+ }
+
+ return CRYPT_OK;
+}
+
+#endif
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/bit/der_length_bit_string.c,v $ */
+/* $Revision: 1.3 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/boolean/der_decode_boolean.c b/crypto/userspace/libtomcrypt/pk/asn1/der/boolean/der_decode_boolean.c
new file mode 100644
index 0000000..f374aa6
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/boolean/der_decode_boolean.c
@@ -0,0 +1,47 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_decode_boolean.c
+ ASN.1 DER, decode a BOOLEAN, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Read a BOOLEAN
+ @param in The destination for the DER encoded BOOLEAN
+ @param inlen The size of the DER BOOLEAN
+ @param out [out] The boolean to decode
+ @return CRYPT_OK if successful
+*/
+int der_decode_boolean(const unsigned char *in, unsigned long inlen,
+ int *out)
+{
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ if (inlen != 3 || in[0] != 0x01 || in[1] != 0x01 || (in[2] != 0x00 && in[2] != 0xFF)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ *out = (in[2]==0xFF) ? 1 : 0;
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/boolean/der_decode_boolean.c,v $ */
+/* $Revision: 1.2 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/boolean/der_encode_boolean.c b/crypto/userspace/libtomcrypt/pk/asn1/der/boolean/der_encode_boolean.c
new file mode 100644
index 0000000..df497bf
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/boolean/der_encode_boolean.c
@@ -0,0 +1,51 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_encode_boolean.c
+ ASN.1 DER, encode a BOOLEAN, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Store a BOOLEAN
+ @param in The boolean to encode
+ @param out [out] The destination for the DER encoded BOOLEAN
+ @param outlen [in/out] The max size and resulting size of the DER BOOLEAN
+ @return CRYPT_OK if successful
+*/
+int der_encode_boolean(int in,
+ unsigned char *out, unsigned long *outlen)
+{
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ if (*outlen < 3) {
+ *outlen = 3;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ *outlen = 3;
+ out[0] = 0x01;
+ out[1] = 0x01;
+ out[2] = in ? 0xFF : 0x00;
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/boolean/der_encode_boolean.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/boolean/der_length_boolean.c b/crypto/userspace/libtomcrypt/pk/asn1/der/boolean/der_length_boolean.c
new file mode 100644
index 0000000..aa3e03d
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/boolean/der_length_boolean.c
@@ -0,0 +1,35 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_length_boolean.c
+ ASN.1 DER, get length of a BOOLEAN, Tom St Denis
+*/
+
+#ifdef LTC_DER
+/**
+ Gets length of DER encoding of a BOOLEAN
+ @param outlen [out] The length of the DER encoding
+ @return CRYPT_OK if successful
+*/
+int der_length_boolean(unsigned long *outlen)
+{
+ LTC_ARGCHK(outlen != NULL);
+ *outlen = 3;
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/boolean/der_length_boolean.c,v $ */
+/* $Revision: 1.3 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/choice/der_decode_choice.c b/crypto/userspace/libtomcrypt/pk/asn1/der/choice/der_decode_choice.c
new file mode 100644
index 0000000..277c731
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/choice/der_decode_choice.c
@@ -0,0 +1,182 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_decode_choice.c
+ ASN.1 DER, decode a CHOICE, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/**
+ Decode a CHOICE
+ @param in The DER encoded input
+ @param inlen [in/out] The size of the input and resulting size of read type
+ @param list The list of items to decode
+ @param outlen The number of items in the list
+ @return CRYPT_OK on success
+*/
+int der_decode_choice(const unsigned char *in, unsigned long *inlen,
+ ltc_asn1_list *list, unsigned long outlen)
+{
+ unsigned long size, x, z;
+ void *data;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(inlen != NULL);
+ LTC_ARGCHK(list != NULL);
+
+ /* get blk size */
+ if (*inlen < 2) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* set all of the "used" flags to zero */
+ for (x = 0; x < outlen; x++) {
+ list[x].used = 0;
+ }
+
+ /* now scan until we have a winner */
+ for (x = 0; x < outlen; x++) {
+ size = list[x].size;
+ data = list[x].data;
+
+ switch (list[x].type) {
+ case LTC_ASN1_INTEGER:
+ if (der_decode_integer(in, *inlen, data) == CRYPT_OK) {
+ if (der_length_integer(data, &z) == CRYPT_OK) {
+ list[x].used = 1;
+ *inlen = z;
+ return CRYPT_OK;
+ }
+ }
+ break;
+
+ case LTC_ASN1_SHORT_INTEGER:
+ if (der_decode_short_integer(in, *inlen, data) == CRYPT_OK) {
+ if (der_length_short_integer(size, &z) == CRYPT_OK) {
+ list[x].used = 1;
+ *inlen = z;
+ return CRYPT_OK;
+ }
+ }
+ break;
+
+ case LTC_ASN1_BIT_STRING:
+ if (der_decode_bit_string(in, *inlen, data, &size) == CRYPT_OK) {
+ if (der_length_bit_string(size, &z) == CRYPT_OK) {
+ list[x].used = 1;
+ list[x].size = size;
+ *inlen = z;
+ return CRYPT_OK;
+ }
+ }
+ break;
+
+ case LTC_ASN1_OCTET_STRING:
+ if (der_decode_octet_string(in, *inlen, data, &size) == CRYPT_OK) {
+ if (der_length_octet_string(size, &z) == CRYPT_OK) {
+ list[x].used = 1;
+ list[x].size = size;
+ *inlen = z;
+ return CRYPT_OK;
+ }
+ }
+ break;
+
+ case LTC_ASN1_NULL:
+ if (*inlen == 2 && in[x] == 0x05 && in[x+1] == 0x00) {
+ *inlen = 2;
+ list[x].used = 1;
+ return CRYPT_OK;
+ }
+ break;
+
+ case LTC_ASN1_OBJECT_IDENTIFIER:
+ if (der_decode_object_identifier(in, *inlen, data, &size) == CRYPT_OK) {
+ if (der_length_object_identifier(data, size, &z) == CRYPT_OK) {
+ list[x].used = 1;
+ list[x].size = size;
+ *inlen = z;
+ return CRYPT_OK;
+ }
+ }
+ break;
+
+ case LTC_ASN1_IA5_STRING:
+ if (der_decode_ia5_string(in, *inlen, data, &size) == CRYPT_OK) {
+ if (der_length_ia5_string(data, size, &z) == CRYPT_OK) {
+ list[x].used = 1;
+ list[x].size = size;
+ *inlen = z;
+ return CRYPT_OK;
+ }
+ }
+ break;
+
+
+ case LTC_ASN1_PRINTABLE_STRING:
+ if (der_decode_printable_string(in, *inlen, data, &size) == CRYPT_OK) {
+ if (der_length_printable_string(data, size, &z) == CRYPT_OK) {
+ list[x].used = 1;
+ list[x].size = size;
+ *inlen = z;
+ return CRYPT_OK;
+ }
+ }
+ break;
+
+ case LTC_ASN1_UTF8_STRING:
+ if (der_decode_utf8_string(in, *inlen, data, &size) == CRYPT_OK) {
+ if (der_length_utf8_string(data, size, &z) == CRYPT_OK) {
+ list[x].used = 1;
+ list[x].size = size;
+ *inlen = z;
+ return CRYPT_OK;
+ }
+ }
+ break;
+
+ case LTC_ASN1_UTCTIME:
+ z = *inlen;
+ if (der_decode_utctime(in, &z, data) == CRYPT_OK) {
+ list[x].used = 1;
+ *inlen = z;
+ return CRYPT_OK;
+ }
+ break;
+
+ case LTC_ASN1_SET:
+ case LTC_ASN1_SETOF:
+ case LTC_ASN1_SEQUENCE:
+ if (der_decode_sequence(in, *inlen, data, size) == CRYPT_OK) {
+ if (der_length_sequence(data, size, &z) == CRYPT_OK) {
+ list[x].used = 1;
+ *inlen = z;
+ return CRYPT_OK;
+ }
+ }
+ break;
+
+ default:
+ return CRYPT_INVALID_ARG;
+ }
+ }
+
+ return CRYPT_INVALID_PACKET;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/choice/der_decode_choice.c,v $ */
+/* $Revision: 1.9 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/ia5/der_decode_ia5_string.c b/crypto/userspace/libtomcrypt/pk/asn1/der/ia5/der_decode_ia5_string.c
new file mode 100644
index 0000000..001477b
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/ia5/der_decode_ia5_string.c
@@ -0,0 +1,96 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_decode_ia5_string.c
+ ASN.1 DER, encode a IA5 STRING, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Store a IA5 STRING
+ @param in The DER encoded IA5 STRING
+ @param inlen The size of the DER IA5 STRING
+ @param out [out] The array of octets stored (one per char)
+ @param outlen [in/out] The number of octets stored
+ @return CRYPT_OK if successful
+*/
+int der_decode_ia5_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long x, y, len;
+ int t;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* must have header at least */
+ if (inlen < 2) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* check for 0x16 */
+ if ((in[0] & 0x1F) != 0x16) {
+ return CRYPT_INVALID_PACKET;
+ }
+ x = 1;
+
+ /* decode the length */
+ if (in[x] & 0x80) {
+ /* valid # of bytes in length are 1,2,3 */
+ y = in[x] & 0x7F;
+ if ((y == 0) || (y > 3) || ((x + y) > inlen)) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* read the length in */
+ len = 0;
+ ++x;
+ while (y--) {
+ len = (len << 8) | in[x++];
+ }
+ } else {
+ len = in[x++] & 0x7F;
+ }
+
+ /* is it too long? */
+ if (len > *outlen) {
+ *outlen = len;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ if (len + x > inlen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* read the data */
+ for (y = 0; y < len; y++) {
+ t = der_ia5_value_decode(in[x++]);
+ if (t == -1) {
+ return CRYPT_INVALID_ARG;
+ }
+ out[y] = t;
+ }
+
+ *outlen = y;
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/ia5/der_decode_ia5_string.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/ia5/der_encode_ia5_string.c b/crypto/userspace/libtomcrypt/pk/asn1/der/ia5/der_encode_ia5_string.c
new file mode 100644
index 0000000..82ed466
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/ia5/der_encode_ia5_string.c
@@ -0,0 +1,85 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_encode_ia5_string.c
+ ASN.1 DER, encode a IA5 STRING, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/**
+ Store an IA5 STRING
+ @param in The array of IA5 to store (one per char)
+ @param inlen The number of IA5 to store
+ @param out [out] The destination for the DER encoded IA5 STRING
+ @param outlen [in/out] The max size and resulting size of the DER IA5 STRING
+ @return CRYPT_OK if successful
+*/
+int der_encode_ia5_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long x, y, len;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* get the size */
+ if ((err = der_length_ia5_string(in, inlen, &len)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* too big? */
+ if (len > *outlen) {
+ *outlen = len;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* encode the header+len */
+ x = 0;
+ out[x++] = 0x16;
+ if (inlen < 128) {
+ out[x++] = (unsigned char)inlen;
+ } else if (inlen < 256) {
+ out[x++] = 0x81;
+ out[x++] = (unsigned char)inlen;
+ } else if (inlen < 65536UL) {
+ out[x++] = 0x82;
+ out[x++] = (unsigned char)((inlen>>8)&255);
+ out[x++] = (unsigned char)(inlen&255);
+ } else if (inlen < 16777216UL) {
+ out[x++] = 0x83;
+ out[x++] = (unsigned char)((inlen>>16)&255);
+ out[x++] = (unsigned char)((inlen>>8)&255);
+ out[x++] = (unsigned char)(inlen&255);
+ } else {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* store octets */
+ for (y = 0; y < inlen; y++) {
+ out[x++] = der_ia5_char_encode(in[y]);
+ }
+
+ /* retun length */
+ *outlen = x;
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/ia5/der_encode_ia5_string.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/ia5/der_length_ia5_string.c b/crypto/userspace/libtomcrypt/pk/asn1/der/ia5/der_length_ia5_string.c
new file mode 100644
index 0000000..4d60f8e
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/ia5/der_length_ia5_string.c
@@ -0,0 +1,194 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_length_ia5_string.c
+ ASN.1 DER, get length of IA5 STRING, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+static const struct {
+ int code, value;
+} ia5_table[] = {
+{ '\0', 0 },
+{ '\a', 7 },
+{ '\b', 8 },
+{ '\t', 9 },
+{ '\n', 10 },
+{ '\f', 12 },
+{ '\r', 13 },
+{ ' ', 32 },
+{ '!', 33 },
+{ '"', 34 },
+{ '#', 35 },
+{ '$', 36 },
+{ '%', 37 },
+{ '&', 38 },
+{ '\'', 39 },
+{ '(', 40 },
+{ ')', 41 },
+{ '*', 42 },
+{ '+', 43 },
+{ ',', 44 },
+{ '-', 45 },
+{ '.', 46 },
+{ '/', 47 },
+{ '0', 48 },
+{ '1', 49 },
+{ '2', 50 },
+{ '3', 51 },
+{ '4', 52 },
+{ '5', 53 },
+{ '6', 54 },
+{ '7', 55 },
+{ '8', 56 },
+{ '9', 57 },
+{ ':', 58 },
+{ ';', 59 },
+{ '<', 60 },
+{ '=', 61 },
+{ '>', 62 },
+{ '?', 63 },
+{ '@', 64 },
+{ 'A', 65 },
+{ 'B', 66 },
+{ 'C', 67 },
+{ 'D', 68 },
+{ 'E', 69 },
+{ 'F', 70 },
+{ 'G', 71 },
+{ 'H', 72 },
+{ 'I', 73 },
+{ 'J', 74 },
+{ 'K', 75 },
+{ 'L', 76 },
+{ 'M', 77 },
+{ 'N', 78 },
+{ 'O', 79 },
+{ 'P', 80 },
+{ 'Q', 81 },
+{ 'R', 82 },
+{ 'S', 83 },
+{ 'T', 84 },
+{ 'U', 85 },
+{ 'V', 86 },
+{ 'W', 87 },
+{ 'X', 88 },
+{ 'Y', 89 },
+{ 'Z', 90 },
+{ '[', 91 },
+{ '\\', 92 },
+{ ']', 93 },
+{ '^', 94 },
+{ '_', 95 },
+{ '`', 96 },
+{ 'a', 97 },
+{ 'b', 98 },
+{ 'c', 99 },
+{ 'd', 100 },
+{ 'e', 101 },
+{ 'f', 102 },
+{ 'g', 103 },
+{ 'h', 104 },
+{ 'i', 105 },
+{ 'j', 106 },
+{ 'k', 107 },
+{ 'l', 108 },
+{ 'm', 109 },
+{ 'n', 110 },
+{ 'o', 111 },
+{ 'p', 112 },
+{ 'q', 113 },
+{ 'r', 114 },
+{ 's', 115 },
+{ 't', 116 },
+{ 'u', 117 },
+{ 'v', 118 },
+{ 'w', 119 },
+{ 'x', 120 },
+{ 'y', 121 },
+{ 'z', 122 },
+{ '{', 123 },
+{ '|', 124 },
+{ '}', 125 },
+{ '~', 126 }
+};
+
+int der_ia5_char_encode(int c)
+{
+ int x;
+ for (x = 0; x < (int)(sizeof(ia5_table)/sizeof(ia5_table[0])); x++) {
+ if (ia5_table[x].code == c) {
+ return ia5_table[x].value;
+ }
+ }
+ return -1;
+}
+
+int der_ia5_value_decode(int v)
+{
+ int x;
+ for (x = 0; x < (int)(sizeof(ia5_table)/sizeof(ia5_table[0])); x++) {
+ if (ia5_table[x].value == v) {
+ return ia5_table[x].code;
+ }
+ }
+ return -1;
+}
+
+/**
+ Gets length of DER encoding of IA5 STRING
+ @param octets The values you want to encode
+ @param noctets The number of octets in the string to encode
+ @param outlen [out] The length of the DER encoding for the given string
+ @return CRYPT_OK if successful
+*/
+int der_length_ia5_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen)
+{
+ unsigned long x;
+
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(octets != NULL);
+
+ /* scan string for validity */
+ for (x = 0; x < noctets; x++) {
+ if (der_ia5_char_encode(octets[x]) == -1) {
+ return CRYPT_INVALID_ARG;
+ }
+ }
+
+ if (noctets < 128) {
+ /* 16 LL DD DD DD ... */
+ *outlen = 2 + noctets;
+ } else if (noctets < 256) {
+ /* 16 81 LL DD DD DD ... */
+ *outlen = 3 + noctets;
+ } else if (noctets < 65536UL) {
+ /* 16 82 LL LL DD DD DD ... */
+ *outlen = 4 + noctets;
+ } else if (noctets < 16777216UL) {
+ /* 16 83 LL LL LL DD DD DD ... */
+ *outlen = 5 + noctets;
+ } else {
+ return CRYPT_INVALID_ARG;
+ }
+
+ return CRYPT_OK;
+}
+
+#endif
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/ia5/der_length_ia5_string.c,v $ */
+/* $Revision: 1.3 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/integer/der_decode_integer.c b/crypto/userspace/libtomcrypt/pk/asn1/der/integer/der_decode_integer.c
new file mode 100644
index 0000000..d7b13cf
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/integer/der_decode_integer.c
@@ -0,0 +1,110 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_decode_integer.c
+ ASN.1 DER, decode an integer, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Read a mp_int integer
+ @param in The DER encoded data
+ @param inlen Size of DER encoded data
+ @param num The first mp_int to decode
+ @return CRYPT_OK if successful
+*/
+int der_decode_integer(const unsigned char *in, unsigned long inlen, mp_int_t num)
+{
+ unsigned long x, y, z;
+ int err;
+
+ LTC_ARGCHK(num != NULL);
+ LTC_ARGCHK(in != NULL);
+
+ /* min DER INTEGER is 0x02 01 00 == 0 */
+ if (inlen < (1 + 1 + 1)) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* ok expect 0x02 when we AND with 0001 1111 [1F] */
+ x = 0;
+ if ((in[x++] & 0x1F) != 0x02) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* now decode the len stuff */
+ z = in[x++];
+
+ if ((z & 0x80) == 0x00) {
+ /* short form */
+
+ /* will it overflow? */
+ if (x + z > inlen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* no so read it */
+ if ((err = mp_read_unsigned_bin(num, (unsigned char *)in + x, z)) != CRYPT_OK) {
+ return err;
+ }
+ } else {
+ /* long form */
+ z &= 0x7F;
+
+ /* will number of length bytes overflow? (or > 4) */
+ if (((x + z) > inlen) || (z > 4) || (z == 0)) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* now read it in */
+ y = 0;
+ while (z--) {
+ y = ((unsigned long)(in[x++])) | (y << 8);
+ }
+
+ /* now will reading y bytes overrun? */
+ if ((x + y) > inlen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* no so read it */
+ if ((err = mp_read_unsigned_bin(num, (unsigned char *)in + x, y)) != CRYPT_OK) {
+ return err;
+ }
+ }
+
+ /* see if it's negative */
+ if (in[x] & 0x80) {
+ mp_int tmp;
+ if (mp_init(&tmp) != CRYPT_OK) {
+ return CRYPT_MEM;
+ }
+
+ if (mp_2expt(&tmp, mp_count_bits(num)) != CRYPT_OK || mp_sub(num, &tmp, num) != CRYPT_OK) {
+ mp_clear(&tmp);
+ return CRYPT_MEM;
+ }
+ mp_clear(&tmp);
+ }
+
+ return CRYPT_OK;
+
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/integer/der_decode_integer.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/integer/der_encode_integer.c b/crypto/userspace/libtomcrypt/pk/asn1/der/integer/der_encode_integer.c
new file mode 100644
index 0000000..830446a
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/integer/der_encode_integer.c
@@ -0,0 +1,130 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_encode_integer.c
+ ASN.1 DER, encode an integer, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/* Exports a positive bignum as DER format (upto 2^32 bytes in size) */
+/**
+ Store a mp_int integer
+ @param num The first mp_int to encode
+ @param out [out] The destination for the DER encoded integers
+ @param outlen [in/out] The max size and resulting size of the DER encoded integers
+ @return CRYPT_OK if successful
+*/
+int der_encode_integer(mp_int_t num, unsigned char *out, unsigned long *outlen)
+{
+ unsigned long tmplen, y;
+ int err, leading_zero;
+
+ LTC_ARGCHK(num != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* find out how big this will be */
+ if ((err = der_length_integer(num, &tmplen)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (*outlen < tmplen) {
+ *outlen = tmplen;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ if (mp_cmp_d(num, 0) != LTC_MP_LT) {
+ /* we only need a leading zero if the msb of the first byte is one */
+ if ((mp_count_bits(num) & 7) == 0 || mp_iszero(num) == LTC_MP_YES) {
+ leading_zero = 1;
+ } else {
+ leading_zero = 0;
+ }
+
+ /* get length of num in bytes (plus 1 since we force the msbyte to zero) */
+ y = mp_unsigned_bin_size(num) + leading_zero;
+ } else {
+ leading_zero = 0;
+ y = mp_count_bits(num);
+ y = y + (8 - (y & 7));
+ y = y >> 3;
+ if (((mp_cnt_lsb(num)+1)==mp_count_bits(num)) && ((mp_count_bits(num)&7)==0)) --y;
+ }
+
+ /* now store initial data */
+ *out++ = 0x02;
+ if (y < 128) {
+ /* short form */
+ *out++ = (unsigned char)y;
+ } else if (y < 256) {
+ *out++ = 0x81;
+ *out++ = (unsigned char)y;
+ } else if (y < 65536UL) {
+ *out++ = 0x82;
+ *out++ = (unsigned char)((y>>8)&255);
+ *out++ = (unsigned char)y;
+ } else if (y < 16777216UL) {
+ *out++ = 0x83;
+ *out++ = (unsigned char)((y>>16)&255);
+ *out++ = (unsigned char)((y>>8)&255);
+ *out++ = (unsigned char)y;
+ } else {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* now store msbyte of zero if num is non-zero */
+ if (leading_zero) {
+ *out++ = 0x00;
+ }
+
+ /* if it's not zero store it as big endian */
+ if (mp_cmp_d(num, 0) == LTC_MP_GT) {
+ /* now store the mpint */
+ if ((err = mp_to_unsigned_bin(num, out)) != CRYPT_OK) {
+ return err;
+ }
+ } else if (mp_iszero(num) != LTC_MP_YES) {
+ mp_int tmp;
+
+ /* negative */
+ if (mp_init(&tmp) != CRYPT_OK) {
+ return CRYPT_MEM;
+ }
+
+ /* 2^roundup and subtract */
+ y = mp_count_bits(num);
+ y = y + (8 - (y & 7));
+ if (((mp_cnt_lsb(num)+1)==mp_count_bits(num)) && ((mp_count_bits(num)&7)==0)) y -= 8;
+ if (mp_2expt(&tmp, y) != CRYPT_OK || mp_add(&tmp, num, &tmp) != CRYPT_OK) {
+ mp_clear(&tmp);
+ return CRYPT_MEM;
+ }
+ if ((err = mp_to_unsigned_bin(&tmp, out)) != CRYPT_OK) {
+ mp_clear(&tmp);
+ return err;
+ }
+ mp_clear(&tmp);
+ }
+
+ /* we good */
+ *outlen = tmplen;
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/integer/der_encode_integer.c,v $ */
+/* $Revision: 1.9 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/integer/der_length_integer.c b/crypto/userspace/libtomcrypt/pk/asn1/der/integer/der_length_integer.c
new file mode 100644
index 0000000..40addd5
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/integer/der_length_integer.c
@@ -0,0 +1,82 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_length_integer.c
+ ASN.1 DER, get length of encoding, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+/**
+ Gets length of DER encoding of num
+ @param num The int to get the size of
+ @param outlen [out] The length of the DER encoding for the given integer
+ @return CRYPT_OK if successful
+*/
+int der_length_integer(mp_int_t num, unsigned long *outlen)
+{
+ unsigned long z, len;
+ int leading_zero;
+
+ LTC_ARGCHK(num != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ if (mp_cmp_d(num, 0) != LTC_MP_LT) {
+ /* positive */
+
+ /* we only need a leading zero if the msb of the first byte is one */
+ if ((mp_count_bits(num) & 7) == 0 || mp_iszero(num) == LTC_MP_YES) {
+ leading_zero = 1;
+ } else {
+ leading_zero = 0;
+ }
+
+ /* size for bignum */
+ z = len = leading_zero + mp_unsigned_bin_size(num);
+ } else {
+ /* it's negative */
+ /* find power of 2 that is a multiple of eight and greater than count bits */
+ leading_zero = 0;
+ z = mp_count_bits(num);
+ z = z + (8 - (z & 7));
+ if (((mp_cnt_lsb(num)+1)==mp_count_bits(num)) && ((mp_count_bits(num)&7)==0)) --z;
+ len = z = z >> 3;
+ }
+
+ /* now we need a length */
+ if (z < 128) {
+ /* short form */
+ ++len;
+ } else {
+ /* long form (relies on z != 0), assumes length bytes < 128 */
+ ++len;
+
+ while (z) {
+ ++len;
+ z >>= 8;
+ }
+ }
+
+ /* we need a 0x02 to indicate it's INTEGER */
+ ++len;
+
+ /* return length */
+ *outlen = len;
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/integer/der_length_integer.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/object_identifier/der_decode_object_identifier.c b/crypto/userspace/libtomcrypt/pk/asn1/der/object_identifier/der_decode_object_identifier.c
new file mode 100644
index 0000000..cdd296d
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/object_identifier/der_decode_object_identifier.c
@@ -0,0 +1,99 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_decode_object_identifier.c
+ ASN.1 DER, Decode Object Identifier, Tom St Denis
+*/
+
+#ifdef LTC_DER
+/**
+ Decode OID data and store the array of integers in words
+ @param in The OID DER encoded data
+ @param inlen The length of the OID data
+ @param words [out] The destination of the OID words
+ @param outlen [in/out] The number of OID words
+ @return CRYPT_OK if successful
+*/
+int der_decode_object_identifier(const unsigned char *in, unsigned long inlen,
+ unsigned long *words, unsigned long *outlen)
+{
+ unsigned long x, y, t, len;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(words != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* header is at least 3 bytes */
+ if (inlen < 3) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* must be room for at least two words */
+ if (*outlen < 2) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* decode the packet header */
+ x = 0;
+ if ((in[x++] & 0x1F) != 0x06) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* get the length */
+ if (in[x] < 128) {
+ len = in[x++];
+ } else {
+ if (in[x] < 0x81 || in[x] > 0x82) {
+ return CRYPT_INVALID_PACKET;
+ }
+ y = in[x++] & 0x7F;
+ len = 0;
+ while (y--) {
+ len = (len << 8) | (unsigned long)in[x++];
+ }
+ }
+
+ if (len < 1 || (len + x) > inlen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* decode words */
+ y = 0;
+ t = 0;
+ while (len--) {
+ t = (t << 7) | (in[x] & 0x7F);
+ if (!(in[x++] & 0x80)) {
+ /* store t */
+ if (y >= *outlen) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+ if (y == 0) {
+ words[0] = t / 40;
+ words[1] = t % 40;
+ y = 2;
+ } else {
+ words[y++] = t;
+ }
+ t = 0;
+ }
+ }
+
+ *outlen = y;
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/object_identifier/der_decode_object_identifier.c,v $ */
+/* $Revision: 1.6 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/object_identifier/der_encode_object_identifier.c b/crypto/userspace/libtomcrypt/pk/asn1/der/object_identifier/der_encode_object_identifier.c
new file mode 100644
index 0000000..b26ebdf
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/object_identifier/der_encode_object_identifier.c
@@ -0,0 +1,111 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_encode_object_identifier.c
+ ASN.1 DER, Encode Object Identifier, Tom St Denis
+*/
+
+#ifdef LTC_DER
+/**
+ Encode an OID
+ @param words The words to encode (upto 32-bits each)
+ @param nwords The number of words in the OID
+ @param out [out] Destination of OID data
+ @param outlen [in/out] The max and resulting size of the OID
+ @return CRYPT_OK if successful
+*/
+int der_encode_object_identifier(unsigned long *words, unsigned long nwords,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long i, x, y, z, t, mask, wordbuf;
+ int err;
+
+ LTC_ARGCHK(words != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* check length */
+ if ((err = der_length_object_identifier(words, nwords, &x)) != CRYPT_OK) {
+ return err;
+ }
+ if (x > *outlen) {
+ *outlen = x;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* compute length to store OID data */
+ z = 0;
+ wordbuf = words[0] * 40 + words[1];
+ for (y = 1; y < nwords; y++) {
+ t = der_object_identifier_bits(wordbuf);
+ z += t/7 + ((t%7) ? 1 : 0) + (wordbuf == 0 ? 1 : 0);
+ if (y < nwords - 1) {
+ wordbuf = words[y + 1];
+ }
+ }
+
+ /* store header + length */
+ x = 0;
+ out[x++] = 0x06;
+ if (z < 128) {
+ out[x++] = (unsigned char)z;
+ } else if (z < 256) {
+ out[x++] = 0x81;
+ out[x++] = (unsigned char)z;
+ } else if (z < 65536UL) {
+ out[x++] = 0x82;
+ out[x++] = (unsigned char)((z>>8)&255);
+ out[x++] = (unsigned char)(z&255);
+ } else {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* store first byte */
+ wordbuf = words[0] * 40 + words[1];
+ for (i = 1; i < nwords; i++) {
+ /* store 7 bit words in little endian */
+ t = wordbuf & 0xFFFFFFFF;
+ if (t) {
+ y = x;
+ mask = 0;
+ while (t) {
+ out[x++] = (unsigned char)((t & 0x7F) | mask);
+ t >>= 7;
+ mask |= 0x80; /* upper bit is set on all but the last byte */
+ }
+ /* now swap bytes y...x-1 */
+ z = x - 1;
+ while (y < z) {
+ t = out[y]; out[y] = out[z]; out[z] = (unsigned char)t;
+ ++y;
+ --z;
+ }
+ } else {
+ /* zero word */
+ out[x++] = 0x00;
+ }
+
+ if (i < nwords - 1) {
+ wordbuf = words[i + 1];
+ }
+ }
+
+ *outlen = x;
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/object_identifier/der_encode_object_identifier.c,v $ */
+/* $Revision: 1.7 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/object_identifier/der_length_object_identifier.c b/crypto/userspace/libtomcrypt/pk/asn1/der/object_identifier/der_length_object_identifier.c
new file mode 100644
index 0000000..ada54ab
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/object_identifier/der_length_object_identifier.c
@@ -0,0 +1,89 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_length_object_identifier.c
+ ASN.1 DER, get length of Object Identifier, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+unsigned long der_object_identifier_bits(unsigned long x)
+{
+ unsigned long c;
+ x &= 0xFFFFFFFF;
+ c = 0;
+ while (x) {
+ ++c;
+ x >>= 1;
+ }
+ return c;
+}
+
+
+/**
+ Gets length of DER encoding of Object Identifier
+ @param nwords The number of OID words
+ @param words The actual OID words to get the size of
+ @param outlen [out] The length of the DER encoding for the given string
+ @return CRYPT_OK if successful
+*/
+int der_length_object_identifier(unsigned long *words, unsigned long nwords, unsigned long *outlen)
+{
+ unsigned long y, z, t, wordbuf;
+
+ LTC_ARGCHK(words != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+
+ /* must be >= 2 words */
+ if (nwords < 2) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* word1 = 0,1,2,3 and word2 0..39 */
+ if (words[0] > 3 || (words[0] < 2 && words[1] > 39)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* leading word is the first two */
+ z = 0;
+ wordbuf = words[0] * 40 + words[1];
+ for (y = 1; y < nwords; y++) {
+ t = der_object_identifier_bits(wordbuf);
+ z += t/7 + ((t%7) ? 1 : 0) + (wordbuf == 0 ? 1 : 0);
+ if (y < nwords - 1) {
+ /* grab next word */
+ wordbuf = words[y+1];
+ }
+ }
+
+ /* now depending on the length our length encoding changes */
+ if (z < 128) {
+ z += 2;
+ } else if (z < 256) {
+ z += 3;
+ } else if (z < 65536UL) {
+ z += 4;
+ } else {
+ return CRYPT_INVALID_ARG;
+ }
+
+ *outlen = z;
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/object_identifier/der_length_object_identifier.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/octet/der_decode_octet_string.c b/crypto/userspace/libtomcrypt/pk/asn1/der/octet/der_decode_octet_string.c
new file mode 100644
index 0000000..ab5bc10
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/octet/der_decode_octet_string.c
@@ -0,0 +1,91 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_decode_octet_string.c
+ ASN.1 DER, encode a OCTET STRING, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Store a OCTET STRING
+ @param in The DER encoded OCTET STRING
+ @param inlen The size of the DER OCTET STRING
+ @param out [out] The array of octets stored (one per char)
+ @param outlen [in/out] The number of octets stored
+ @return CRYPT_OK if successful
+*/
+int der_decode_octet_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long x, y, len;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* must have header at least */
+ if (inlen < 2) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* check for 0x04 */
+ if ((in[0] & 0x1F) != 0x04) {
+ return CRYPT_INVALID_PACKET;
+ }
+ x = 1;
+
+ /* decode the length */
+ if (in[x] & 0x80) {
+ /* valid # of bytes in length are 1,2,3 */
+ y = in[x] & 0x7F;
+ if ((y == 0) || (y > 3) || ((x + y) > inlen)) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* read the length in */
+ len = 0;
+ ++x;
+ while (y--) {
+ len = (len << 8) | in[x++];
+ }
+ } else {
+ len = in[x++] & 0x7F;
+ }
+
+ /* is it too long? */
+ if (len > *outlen) {
+ *outlen = len;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ if (len + x > inlen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* read the data */
+ for (y = 0; y < len; y++) {
+ out[y] = in[x++];
+ }
+
+ *outlen = y;
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/octet/der_decode_octet_string.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/octet/der_encode_octet_string.c b/crypto/userspace/libtomcrypt/pk/asn1/der/octet/der_encode_octet_string.c
new file mode 100644
index 0000000..64a0770
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/octet/der_encode_octet_string.c
@@ -0,0 +1,86 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_encode_octet_string.c
+ ASN.1 DER, encode a OCTET STRING, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Store an OCTET STRING
+ @param in The array of OCTETS to store (one per char)
+ @param inlen The number of OCTETS to store
+ @param out [out] The destination for the DER encoded OCTET STRING
+ @param outlen [in/out] The max size and resulting size of the DER OCTET STRING
+ @return CRYPT_OK if successful
+*/
+int der_encode_octet_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long x, y, len;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* get the size */
+ if ((err = der_length_octet_string(inlen, &len)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* too big? */
+ if (len > *outlen) {
+ *outlen = len;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* encode the header+len */
+ x = 0;
+ out[x++] = 0x04;
+ if (inlen < 128) {
+ out[x++] = (unsigned char)inlen;
+ } else if (inlen < 256) {
+ out[x++] = 0x81;
+ out[x++] = (unsigned char)inlen;
+ } else if (inlen < 65536UL) {
+ out[x++] = 0x82;
+ out[x++] = (unsigned char)((inlen>>8)&255);
+ out[x++] = (unsigned char)(inlen&255);
+ } else if (inlen < 16777216UL) {
+ out[x++] = 0x83;
+ out[x++] = (unsigned char)((inlen>>16)&255);
+ out[x++] = (unsigned char)((inlen>>8)&255);
+ out[x++] = (unsigned char)(inlen&255);
+ } else {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* store octets */
+ for (y = 0; y < inlen; y++) {
+ out[x++] = in[y];
+ }
+
+ /* retun length */
+ *outlen = x;
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/octet/der_encode_octet_string.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/octet/der_length_octet_string.c b/crypto/userspace/libtomcrypt/pk/asn1/der/octet/der_length_octet_string.c
new file mode 100644
index 0000000..c494159
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/octet/der_length_octet_string.c
@@ -0,0 +1,53 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_length_octet_string.c
+ ASN.1 DER, get length of OCTET STRING, Tom St Denis
+*/
+
+#ifdef LTC_DER
+/**
+ Gets length of DER encoding of OCTET STRING
+ @param noctets The number of octets in the string to encode
+ @param outlen [out] The length of the DER encoding for the given string
+ @return CRYPT_OK if successful
+*/
+int der_length_octet_string(unsigned long noctets, unsigned long *outlen)
+{
+ LTC_ARGCHK(outlen != NULL);
+
+ if (noctets < 128) {
+ /* 04 LL DD DD DD ... */
+ *outlen = 2 + noctets;
+ } else if (noctets < 256) {
+ /* 04 81 LL DD DD DD ... */
+ *outlen = 3 + noctets;
+ } else if (noctets < 65536UL) {
+ /* 04 82 LL LL DD DD DD ... */
+ *outlen = 4 + noctets;
+ } else if (noctets < 16777216UL) {
+ /* 04 83 LL LL LL DD DD DD ... */
+ *outlen = 5 + noctets;
+ } else {
+ return CRYPT_INVALID_ARG;
+ }
+
+ return CRYPT_OK;
+}
+
+#endif
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/octet/der_length_octet_string.c,v $ */
+/* $Revision: 1.3 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/printable_string/der_decode_printable_string.c b/crypto/userspace/libtomcrypt/pk/asn1/der/printable_string/der_decode_printable_string.c
new file mode 100644
index 0000000..8504f77
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/printable_string/der_decode_printable_string.c
@@ -0,0 +1,96 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_decode_printable_string.c
+ ASN.1 DER, encode a printable STRING, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Store a printable STRING
+ @param in The DER encoded printable STRING
+ @param inlen The size of the DER printable STRING
+ @param out [out] The array of octets stored (one per char)
+ @param outlen [in/out] The number of octets stored
+ @return CRYPT_OK if successful
+*/
+int der_decode_printable_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long x, y, len;
+ int t;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* must have header at least */
+ if (inlen < 2) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* check for 0x13 */
+ if ((in[0] & 0x1F) != 0x13) {
+ return CRYPT_INVALID_PACKET;
+ }
+ x = 1;
+
+ /* decode the length */
+ if (in[x] & 0x80) {
+ /* valid # of bytes in length are 1,2,3 */
+ y = in[x] & 0x7F;
+ if ((y == 0) || (y > 3) || ((x + y) > inlen)) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* read the length in */
+ len = 0;
+ ++x;
+ while (y--) {
+ len = (len << 8) | in[x++];
+ }
+ } else {
+ len = in[x++] & 0x7F;
+ }
+
+ /* is it too long? */
+ if (len > *outlen) {
+ *outlen = len;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ if (len + x > inlen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* read the data */
+ for (y = 0; y < len; y++) {
+ t = der_printable_value_decode(in[x++]);
+ if (t == -1) {
+ return CRYPT_INVALID_ARG;
+ }
+ out[y] = t;
+ }
+
+ *outlen = y;
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/printable_string/der_decode_printable_string.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/printable_string/der_encode_printable_string.c b/crypto/userspace/libtomcrypt/pk/asn1/der/printable_string/der_encode_printable_string.c
new file mode 100644
index 0000000..deccdee
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/printable_string/der_encode_printable_string.c
@@ -0,0 +1,85 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_encode_printable_string.c
+ ASN.1 DER, encode a printable STRING, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/**
+ Store an printable STRING
+ @param in The array of printable to store (one per char)
+ @param inlen The number of printable to store
+ @param out [out] The destination for the DER encoded printable STRING
+ @param outlen [in/out] The max size and resulting size of the DER printable STRING
+ @return CRYPT_OK if successful
+*/
+int der_encode_printable_string(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long x, y, len;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* get the size */
+ if ((err = der_length_printable_string(in, inlen, &len)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* too big? */
+ if (len > *outlen) {
+ *outlen = len;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* encode the header+len */
+ x = 0;
+ out[x++] = 0x13;
+ if (inlen < 128) {
+ out[x++] = (unsigned char)inlen;
+ } else if (inlen < 256) {
+ out[x++] = 0x81;
+ out[x++] = (unsigned char)inlen;
+ } else if (inlen < 65536UL) {
+ out[x++] = 0x82;
+ out[x++] = (unsigned char)((inlen>>8)&255);
+ out[x++] = (unsigned char)(inlen&255);
+ } else if (inlen < 16777216UL) {
+ out[x++] = 0x83;
+ out[x++] = (unsigned char)((inlen>>16)&255);
+ out[x++] = (unsigned char)((inlen>>8)&255);
+ out[x++] = (unsigned char)(inlen&255);
+ } else {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* store octets */
+ for (y = 0; y < inlen; y++) {
+ out[x++] = der_printable_char_encode(in[y]);
+ }
+
+ /* retun length */
+ *outlen = x;
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/printable_string/der_encode_printable_string.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/printable_string/der_length_printable_string.c b/crypto/userspace/libtomcrypt/pk/asn1/der/printable_string/der_length_printable_string.c
new file mode 100644
index 0000000..997d3b5
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/printable_string/der_length_printable_string.c
@@ -0,0 +1,166 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_length_printable_string.c
+ ASN.1 DER, get length of Printable STRING, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+static const struct {
+ int code, value;
+} printable_table[] = {
+{ ' ', 32 },
+{ '\'', 39 },
+{ '(', 40 },
+{ ')', 41 },
+{ '+', 43 },
+{ ',', 44 },
+{ '-', 45 },
+{ '.', 46 },
+{ '/', 47 },
+{ '0', 48 },
+{ '1', 49 },
+{ '2', 50 },
+{ '3', 51 },
+{ '4', 52 },
+{ '5', 53 },
+{ '6', 54 },
+{ '7', 55 },
+{ '8', 56 },
+{ '9', 57 },
+{ ':', 58 },
+{ '=', 61 },
+{ '?', 63 },
+{ 'A', 65 },
+{ 'B', 66 },
+{ 'C', 67 },
+{ 'D', 68 },
+{ 'E', 69 },
+{ 'F', 70 },
+{ 'G', 71 },
+{ 'H', 72 },
+{ 'I', 73 },
+{ 'J', 74 },
+{ 'K', 75 },
+{ 'L', 76 },
+{ 'M', 77 },
+{ 'N', 78 },
+{ 'O', 79 },
+{ 'P', 80 },
+{ 'Q', 81 },
+{ 'R', 82 },
+{ 'S', 83 },
+{ 'T', 84 },
+{ 'U', 85 },
+{ 'V', 86 },
+{ 'W', 87 },
+{ 'X', 88 },
+{ 'Y', 89 },
+{ 'Z', 90 },
+{ 'a', 97 },
+{ 'b', 98 },
+{ 'c', 99 },
+{ 'd', 100 },
+{ 'e', 101 },
+{ 'f', 102 },
+{ 'g', 103 },
+{ 'h', 104 },
+{ 'i', 105 },
+{ 'j', 106 },
+{ 'k', 107 },
+{ 'l', 108 },
+{ 'm', 109 },
+{ 'n', 110 },
+{ 'o', 111 },
+{ 'p', 112 },
+{ 'q', 113 },
+{ 'r', 114 },
+{ 's', 115 },
+{ 't', 116 },
+{ 'u', 117 },
+{ 'v', 118 },
+{ 'w', 119 },
+{ 'x', 120 },
+{ 'y', 121 },
+{ 'z', 122 },
+};
+
+int der_printable_char_encode(int c)
+{
+ int x;
+ for (x = 0; x < (int)(sizeof(printable_table)/sizeof(printable_table[0])); x++) {
+ if (printable_table[x].code == c) {
+ return printable_table[x].value;
+ }
+ }
+ return -1;
+}
+
+int der_printable_value_decode(int v)
+{
+ int x;
+ for (x = 0; x < (int)(sizeof(printable_table)/sizeof(printable_table[0])); x++) {
+ if (printable_table[x].value == v) {
+ return printable_table[x].code;
+ }
+ }
+ return -1;
+}
+
+/**
+ Gets length of DER encoding of Printable STRING
+ @param octets The values you want to encode
+ @param noctets The number of octets in the string to encode
+ @param outlen [out] The length of the DER encoding for the given string
+ @return CRYPT_OK if successful
+*/
+int der_length_printable_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen)
+{
+ unsigned long x;
+
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(octets != NULL);
+
+ /* scan string for validity */
+ for (x = 0; x < noctets; x++) {
+ if (der_printable_char_encode(octets[x]) == -1) {
+ return CRYPT_INVALID_ARG;
+ }
+ }
+
+ if (noctets < 128) {
+ /* 16 LL DD DD DD ... */
+ *outlen = 2 + noctets;
+ } else if (noctets < 256) {
+ /* 16 81 LL DD DD DD ... */
+ *outlen = 3 + noctets;
+ } else if (noctets < 65536UL) {
+ /* 16 82 LL LL DD DD DD ... */
+ *outlen = 4 + noctets;
+ } else if (noctets < 16777216UL) {
+ /* 16 83 LL LL LL DD DD DD ... */
+ *outlen = 5 + noctets;
+ } else {
+ return CRYPT_INVALID_ARG;
+ }
+
+ return CRYPT_OK;
+}
+
+#endif
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/printable_string/der_length_printable_string.c,v $ */
+/* $Revision: 1.3 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_ex.c b/crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_ex.c
new file mode 100644
index 0000000..2067437
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_ex.c
@@ -0,0 +1,287 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include <stdarg.h>
+
+
+/**
+ @file der_decode_sequence_ex.c
+ ASN.1 DER, decode a SEQUENCE, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/**
+ Decode a SEQUENCE
+ @param in The DER encoded input
+ @param inlen The size of the input
+ @param list The list of items to decode
+ @param outlen The number of items in the list
+ @param ordered Search an unordeded or ordered list
+ @return CRYPT_OK on success
+*/
+int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen,
+ ltc_asn1_list *list, unsigned long outlen, int ordered)
+{
+ int err, type;
+ unsigned long size, x, y, z, i, blksize;
+ void *data;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(list != NULL);
+
+ /* get blk size */
+ if (inlen < 2) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* sequence type? We allow 0x30 SEQUENCE and 0x31 SET since fundamentally they're the same structure */
+ x = 0;
+ if (in[x] != 0x30 && in[x] != 0x31) {
+ return CRYPT_INVALID_PACKET;
+ }
+ ++x;
+
+ if (in[x] < 128) {
+ blksize = in[x++];
+ } else if (in[x] & 0x80) {
+ if (in[x] < 0x81 || in[x] > 0x83) {
+ return CRYPT_INVALID_PACKET;
+ }
+ y = in[x++] & 0x7F;
+
+ /* would reading the len bytes overrun? */
+ if (x + y > inlen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* read len */
+ blksize = 0;
+ while (y--) {
+ blksize = (blksize << 8) | (unsigned long)in[x++];
+ }
+ }
+
+ /* would this blksize overflow? */
+ if (x + blksize > inlen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* mark all as unused */
+ for (i = 0; i < outlen; i++) {
+ list[i].used = 0;
+ }
+
+ /* ok read data */
+ inlen = blksize;
+ for (i = 0; i < outlen; i++) {
+ z = 0;
+ type = list[i].type;
+ size = list[i].size;
+ data = list[i].data;
+ if (!ordered && list[i].used == 1) { continue; }
+
+ if (type == LTC_ASN1_EOL) {
+ break;
+ }
+
+ switch (type) {
+ case LTC_ASN1_BOOLEAN:
+ z = inlen;
+ if ((err = der_decode_boolean(in + x, z, ((int *)data))) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ if ((err = der_length_boolean(&z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_INTEGER:
+ z = inlen;
+ if ((err = der_decode_integer(in + x, z, data)) != CRYPT_OK) {
+ if (!ordered) { continue; }
+ goto LBL_ERR;
+ }
+ if ((err = der_length_integer(data, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_SHORT_INTEGER:
+ z = inlen;
+ if ((err = der_decode_short_integer(in + x, z, data)) != CRYPT_OK) {
+ if (!ordered) { continue; }
+ goto LBL_ERR;
+ }
+ if ((err = der_length_short_integer(((unsigned long*)data)[0], &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ break;
+
+ case LTC_ASN1_BIT_STRING:
+ z = inlen;
+ if ((err = der_decode_bit_string(in + x, z, data, &size)) != CRYPT_OK) {
+ if (!ordered) { continue; }
+ goto LBL_ERR;
+ }
+ list[i].size = size;
+ if ((err = der_length_bit_string(size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_OCTET_STRING:
+ z = inlen;
+ if ((err = der_decode_octet_string(in + x, z, data, &size)) != CRYPT_OK) {
+ if (!ordered) { continue; }
+ goto LBL_ERR;
+ }
+ list[i].size = size;
+ if ((err = der_length_octet_string(size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_NULL:
+ if (inlen < 2 || in[x] != 0x05 || in[x+1] != 0x00) {
+ if (!ordered) { continue; }
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+ z = 2;
+ break;
+
+ case LTC_ASN1_OBJECT_IDENTIFIER:
+ z = inlen;
+ if ((err = der_decode_object_identifier(in + x, z, data, &size)) != CRYPT_OK) {
+ if (!ordered) { continue; }
+ goto LBL_ERR;
+ }
+ list[i].size = size;
+ if ((err = der_length_object_identifier(data, size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_IA5_STRING:
+ z = inlen;
+ if ((err = der_decode_ia5_string(in + x, z, data, &size)) != CRYPT_OK) {
+ if (!ordered) { continue; }
+ goto LBL_ERR;
+ }
+ list[i].size = size;
+ if ((err = der_length_ia5_string(data, size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+
+ case LTC_ASN1_PRINTABLE_STRING:
+ z = inlen;
+ if ((err = der_decode_printable_string(in + x, z, data, &size)) != CRYPT_OK) {
+ if (!ordered) { continue; }
+ goto LBL_ERR;
+ }
+ list[i].size = size;
+ if ((err = der_length_printable_string(data, size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_UTF8_STRING:
+ z = inlen;
+ if ((err = der_decode_utf8_string(in + x, z, data, &size)) != CRYPT_OK) {
+ if (!ordered) { continue; }
+ goto LBL_ERR;
+ }
+ list[i].size = size;
+ if ((err = der_length_utf8_string(data, size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_UTCTIME:
+ z = inlen;
+ if ((err = der_decode_utctime(in + x, &z, data)) != CRYPT_OK) {
+ if (!ordered) { continue; }
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_SET:
+ z = inlen;
+ if ((err = der_decode_set(in + x, z, data, size)) != CRYPT_OK) {
+ if (!ordered) { continue; }
+ goto LBL_ERR;
+ }
+ if ((err = der_length_sequence(data, size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+ case LTC_ASN1_SETOF:
+ case LTC_ASN1_SEQUENCE:
+ /* detect if we have the right type */
+ if ((type == LTC_ASN1_SETOF && (in[x] & 0x3F) != 0x31) || (type == LTC_ASN1_SEQUENCE && (in[x] & 0x3F) != 0x30)) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+
+ z = inlen;
+ if ((err = der_decode_sequence(in + x, z, data, size)) != CRYPT_OK) {
+ if (!ordered) { continue; }
+ goto LBL_ERR;
+ }
+ if ((err = der_length_sequence(data, size, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ break;
+
+
+ case LTC_ASN1_CHOICE:
+ z = inlen;
+ if ((err = der_decode_choice(in + x, &z, data, size)) != CRYPT_OK) {
+ if (!ordered) { continue; }
+ goto LBL_ERR;
+ }
+ break;
+
+ default:
+ err = CRYPT_INVALID_ARG;
+ goto LBL_ERR;
+ }
+ x += z;
+ inlen -= z;
+ list[i].used = 1;
+ if (!ordered) {
+ /* restart the decoder */
+ i = -1;
+ }
+ }
+
+ for (i = 0; i < outlen; i++) {
+ if (list[i].used == 0) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+ }
+ err = CRYPT_OK;
+
+LBL_ERR:
+ return err;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_ex.c,v $ */
+/* $Revision: 1.16 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_flexi.c b/crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_flexi.c
new file mode 100644
index 0000000..3f01a57
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_flexi.c
@@ -0,0 +1,394 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include <linux/slab.h>
+
+/**
+ @file der_decode_sequence_flexi.c
+ ASN.1 DER, decode an array of ASN.1 types with a flexi parser, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+static unsigned long fetch_length(const unsigned char *in, unsigned long inlen)
+{
+ unsigned long x, y, z;
+
+ y = 0;
+
+ /* skip type and read len */
+ if (inlen < 2) {
+ return 0xFFFFFFFF;
+ }
+ ++in; ++y;
+
+ /* read len */
+ x = *in++; ++y;
+
+ /* <128 means literal */
+ if (x < 128) {
+ return x+y;
+ }
+ x &= 0x7F; /* the lower 7 bits are the length of the length */
+ inlen -= 2;
+
+ /* len means len of len! */
+ if (x == 0 || x > 4 || x > inlen) {
+ return 0xFFFFFFFF;
+ }
+
+ y += x;
+ z = 0;
+ while (x--) {
+ z = (z<<8) | ((unsigned long)*in);
+ ++in;
+ }
+ return z+y;
+}
+
+/**
+ ASN.1 DER Flexi(ble) decoder will decode arbitrary DER packets and create a linked list of the decoded elements.
+ @param in The input buffer
+ @param inlen [in/out] The length of the input buffer and on output the amount of decoded data
+ @param out [out] A pointer to the linked list
+ @return CRYPT_OK on success.
+*/
+int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out)
+{
+ ltc_asn1_list *l;
+ unsigned long err, type, len, totlen, x, y;
+ void *realloc_tmp;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(inlen != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ l = NULL;
+ totlen = 0;
+
+ /* scan the input and and get lengths and what not */
+ while (*inlen) {
+ /* read the type byte */
+ type = *in;
+
+ /* fetch length */
+ len = fetch_length(in, *inlen);
+ if (len > *inlen) {
+ err = CRYPT_INVALID_PACKET;
+ goto error;
+ }
+
+ /* alloc new link */
+ if (l == NULL) {
+ l = XCALLOC(1, sizeof(*l));
+ if (l == NULL) {
+ err = CRYPT_MEM;
+ goto error;
+ }
+ } else {
+ l->next = XCALLOC(1, sizeof(*l));
+ if (l->next == NULL) {
+ err = CRYPT_MEM;
+ goto error;
+ }
+ l->next->prev = l;
+ l = l->next;
+ }
+
+ /* now switch on type */
+ switch (type) {
+ case 0x01: /* BOOLEAN */
+ l->type = LTC_ASN1_BOOLEAN;
+ l->size = 1;
+ l->data = XCALLOC(1, sizeof(int));
+
+ if ((err = der_decode_boolean(in, *inlen, l->data)) != CRYPT_OK) {
+ goto error;
+ }
+
+ if ((err = der_length_boolean(&len)) != CRYPT_OK) {
+ goto error;
+ }
+ break;
+
+ case 0x02: /* INTEGER */
+ /* init field */
+ l->type = LTC_ASN1_INTEGER;
+ l->size = 1;
+
+ l->data = XMALLOC(sizeof(mp_int));
+ if (l->data == NULL) {
+ err = CRYPT_MEM;
+ goto error;
+ }
+
+ if ((err = mp_init((mp_int_t)l->data)) != CRYPT_OK) {
+ goto error;
+ }
+
+ /* decode field */
+ if ((err = der_decode_integer(in, *inlen, (mp_int_t)l->data)) != CRYPT_OK) {
+ goto error;
+ }
+
+ /* calc length of object */
+ if ((err = der_length_integer((mp_int_t)l->data, &len)) != CRYPT_OK) {
+ goto error;
+ }
+ break;
+
+ case 0x03: /* BIT */
+ /* init field */
+ l->type = LTC_ASN1_BIT_STRING;
+ l->size = len * 8; /* *8 because we store decoded bits one per char and they are encoded 8 per char. */
+
+ if ((l->data = XCALLOC(1, l->size)) == NULL) {
+ err = CRYPT_MEM;
+ goto error;
+ }
+
+ if ((err = der_decode_bit_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) {
+ goto error;
+ }
+
+ if ((err = der_length_bit_string(l->size, &len)) != CRYPT_OK) {
+ goto error;
+ }
+ break;
+
+ case 0x04: /* OCTET */
+
+ /* init field */
+ l->type = LTC_ASN1_OCTET_STRING;
+ l->size = len;
+
+ if ((l->data = XCALLOC(1, l->size)) == NULL) {
+ err = CRYPT_MEM;
+ goto error;
+ }
+
+ if ((err = der_decode_octet_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) {
+ goto error;
+ }
+
+ if ((err = der_length_octet_string(l->size, &len)) != CRYPT_OK) {
+ goto error;
+ }
+ break;
+
+ case 0x05: /* NULL */
+
+ /* valid NULL is 0x05 0x00 */
+ if (in[0] != 0x05 || in[1] != 0x00) {
+ err = CRYPT_INVALID_PACKET;
+ goto error;
+ }
+
+ /* simple to store ;-) */
+ l->type = LTC_ASN1_NULL;
+ l->data = NULL;
+ l->size = 0;
+ len = 2;
+
+ break;
+
+ case 0x06: /* OID */
+
+ /* init field */
+ l->type = LTC_ASN1_OBJECT_IDENTIFIER;
+ l->size = len;
+
+ if ((l->data = XCALLOC(len, sizeof(unsigned long))) == NULL) {
+ err = CRYPT_MEM;
+ goto error;
+ }
+
+ if ((err = der_decode_object_identifier(in, *inlen, l->data, &l->size)) != CRYPT_OK) {
+ goto error;
+ }
+
+ if ((err = der_length_object_identifier(l->data, l->size, &len)) != CRYPT_OK) {
+ goto error;
+ }
+
+ /* resize it to save a bunch of mem */
+ if ((realloc_tmp = XREALLOC(l->data, l->size * sizeof(unsigned long))) == NULL) {
+ /* out of heap but this is not an error */
+ break;
+ }
+ l->data = realloc_tmp;
+ break;
+
+ case 0x0C: /* UTF8 */
+
+ /* init field */
+ l->type = LTC_ASN1_UTF8_STRING;
+ l->size = len;
+
+ if ((l->data = XCALLOC(sizeof(wchar_t), l->size)) == NULL) {
+ err = CRYPT_MEM;
+ goto error;
+ }
+
+ if ((err = der_decode_utf8_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) {
+ goto error;
+ }
+
+ if ((err = der_length_utf8_string(l->data, l->size, &len)) != CRYPT_OK) {
+ goto error;
+ }
+ break;
+
+ case 0x13: /* PRINTABLE */
+
+ /* init field */
+ l->type = LTC_ASN1_PRINTABLE_STRING;
+ l->size = len;
+
+ if ((l->data = XCALLOC(1, l->size)) == NULL) {
+ err = CRYPT_MEM;
+ goto error;
+ }
+
+ if ((err = der_decode_printable_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) {
+ goto error;
+ }
+
+ if ((err = der_length_printable_string(l->data, l->size, &len)) != CRYPT_OK) {
+ goto error;
+ }
+ break;
+
+ case 0x16: /* IA5 */
+
+ /* init field */
+ l->type = LTC_ASN1_IA5_STRING;
+ l->size = len;
+
+ if ((l->data = XCALLOC(1, l->size)) == NULL) {
+ err = CRYPT_MEM;
+ goto error;
+ }
+
+ if ((err = der_decode_ia5_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) {
+ goto error;
+ }
+
+ if ((err = der_length_ia5_string(l->data, l->size, &len)) != CRYPT_OK) {
+ goto error;
+ }
+ break;
+
+ case 0x17: /* UTC TIME */
+
+ /* init field */
+ l->type = LTC_ASN1_UTCTIME;
+ l->size = 1;
+
+ if ((l->data = XCALLOC(1, sizeof(ltc_utctime))) == NULL) {
+ err = CRYPT_MEM;
+ goto error;
+ }
+
+ len = *inlen;
+ if ((err = der_decode_utctime(in, &len, l->data)) != CRYPT_OK) {
+ goto error;
+ }
+
+ if ((err = der_length_utctime(l->data, &len)) != CRYPT_OK) {
+ goto error;
+ }
+ break;
+
+ case 0x30: /* SEQUENCE */
+ case 0x31: /* SET */
+
+ /* init field */
+ l->type = (type == 0x30) ? LTC_ASN1_SEQUENCE : LTC_ASN1_SET;
+
+ /* we have to decode the SEQUENCE header and get it's length */
+
+ /* move past type */
+ ++in; --(*inlen);
+
+ /* read length byte */
+ x = *in++; --(*inlen);
+
+ /* smallest SEQUENCE/SET header */
+ y = 2;
+
+ /* now if it's > 127 the next bytes are the length of the length */
+ if (x > 128) {
+ x &= 0x7F;
+ in += x;
+ *inlen -= x;
+
+ /* update sequence header len */
+ y += x;
+ }
+
+ /* Sequence elements go as child */
+ len = len - y;
+ if ((err = der_decode_sequence_flexi(in, &len, &(l->child))) != CRYPT_OK) {
+ goto error;
+ }
+
+ /* len update */
+ totlen += y;
+
+ /* link them up y0 */
+ l->child->parent = l;
+
+ break;
+ default:
+ /* invalid byte ... this is a soft error */
+ /* remove link */
+ l = l->prev;
+ XFREE(l->next);
+ l->next = NULL;
+ goto outside;
+ }
+
+ /* advance pointers */
+ totlen += len;
+ in += len;
+ *inlen -= len;
+ }
+
+outside:
+
+ /* rewind l please */
+ while (l->prev != NULL || l->parent != NULL) {
+ if (l->parent != NULL) {
+ l = l->parent;
+ } else {
+ l = l->prev;
+ }
+ }
+
+ /* return */
+ *out = l;
+ *inlen = totlen;
+ return CRYPT_OK;
+
+error:
+ /* free list */
+ der_sequence_free(l);
+
+ return err;
+}
+
+#endif
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_flexi.c,v $ */
+/* $Revision: 1.26 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_multi.c b/crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_multi.c
new file mode 100644
index 0000000..d1b7878
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_decode_sequence_multi.c
@@ -0,0 +1,140 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include <stdarg.h>
+#include <linux/slab.h>
+
+
+/**
+ @file der_decode_sequence_multi.c
+ ASN.1 DER, decode a SEQUENCE, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/**
+ Decode a SEQUENCE type using a VA list
+ @param in Input buffer
+ @param inlen Length of input in octets
+ @remark <...> is of the form <type, size, data> (int, unsigned long, void*)
+ @return CRYPT_OK on success
+*/
+int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
+{
+ int err, type;
+ unsigned long size, x;
+ void *data;
+ va_list args;
+ ltc_asn1_list *list;
+
+ LTC_ARGCHK(in != NULL);
+
+ /* get size of output that will be required */
+ va_start(args, inlen);
+ x = 0;
+ for (;;) {
+ type = va_arg(args, int);
+ size = va_arg(args, unsigned long);
+ data = va_arg(args, void*);
+
+ if (type == LTC_ASN1_EOL) {
+ break;
+ }
+
+ switch (type) {
+ case LTC_ASN1_BOOLEAN:
+ case LTC_ASN1_INTEGER:
+ case LTC_ASN1_SHORT_INTEGER:
+ case LTC_ASN1_BIT_STRING:
+ case LTC_ASN1_OCTET_STRING:
+ case LTC_ASN1_NULL:
+ case LTC_ASN1_OBJECT_IDENTIFIER:
+ case LTC_ASN1_IA5_STRING:
+ case LTC_ASN1_PRINTABLE_STRING:
+ case LTC_ASN1_UTF8_STRING:
+ case LTC_ASN1_UTCTIME:
+ case LTC_ASN1_SET:
+ case LTC_ASN1_SETOF:
+ case LTC_ASN1_SEQUENCE:
+ case LTC_ASN1_CHOICE:
+ ++x;
+ break;
+
+ default:
+ va_end(args);
+ return CRYPT_INVALID_ARG;
+ }
+ }
+ va_end(args);
+
+ /* allocate structure for x elements */
+ if (x == 0) {
+ return CRYPT_NOP;
+ }
+
+ list = XCALLOC(sizeof(*list), x);
+ if (list == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* fill in the structure */
+ va_start(args, inlen);
+ x = 0;
+ for (;;) {
+ type = va_arg(args, int);
+ size = va_arg(args, unsigned long);
+ data = va_arg(args, void*);
+
+ if (type == LTC_ASN1_EOL) {
+ break;
+ }
+
+ switch (type) {
+ case LTC_ASN1_BOOLEAN:
+ case LTC_ASN1_INTEGER:
+ case LTC_ASN1_SHORT_INTEGER:
+ case LTC_ASN1_BIT_STRING:
+ case LTC_ASN1_OCTET_STRING:
+ case LTC_ASN1_NULL:
+ case LTC_ASN1_OBJECT_IDENTIFIER:
+ case LTC_ASN1_IA5_STRING:
+ case LTC_ASN1_PRINTABLE_STRING:
+ case LTC_ASN1_UTF8_STRING:
+ case LTC_ASN1_UTCTIME:
+ case LTC_ASN1_SEQUENCE:
+ case LTC_ASN1_SET:
+ case LTC_ASN1_SETOF:
+ case LTC_ASN1_CHOICE:
+ list[x].type = type;
+ list[x].size = size;
+ list[x++].data = data;
+ break;
+
+ default:
+ va_end(args);
+ err = CRYPT_INVALID_ARG;
+ goto LBL_ERR;
+ }
+ }
+ va_end(args);
+
+ err = der_decode_sequence(in, inlen, list, x);
+LBL_ERR:
+ XFREE(list);
+ return err;
+}
+
+#endif
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_multi.c,v $ */
+/* $Revision: 1.13 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_encode_sequence_ex.c b/crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_encode_sequence_ex.c
new file mode 100644
index 0000000..e92f7c3
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_encode_sequence_ex.c
@@ -0,0 +1,335 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include <stdarg.h>
+
+
+/**
+ @file der_encode_sequence_ex.c
+ ASN.1 DER, encode a SEQUENCE, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/**
+ Encode a SEQUENCE
+ @param list The list of items to encode
+ @param inlen The number of items in the list
+ @param out [out] The destination
+ @param outlen [in/out] The size of the output
+ @param type_of LTC_ASN1_SEQUENCE or LTC_ASN1_SET/LTC_ASN1_SETOF
+ @return CRYPT_OK on success
+*/
+int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen, int type_of)
+{
+ int err, type;
+ unsigned long size, x, y, z, i;
+ void *data;
+
+ LTC_ARGCHK(list != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* get size of output that will be required */
+ y = 0;
+ for (i = 0; i < inlen; i++) {
+ type = list[i].type;
+ size = list[i].size;
+ data = list[i].data;
+
+ if (type == LTC_ASN1_EOL) {
+ break;
+ }
+
+ switch (type) {
+ case LTC_ASN1_BOOLEAN:
+ if ((err = der_length_boolean(&x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_INTEGER:
+ if ((err = der_length_integer(data, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_SHORT_INTEGER:
+ if ((err = der_length_short_integer(*((unsigned long*)data), &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_BIT_STRING:
+ if ((err = der_length_bit_string(size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_OCTET_STRING:
+ if ((err = der_length_octet_string(size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_NULL:
+ y += 2;
+ break;
+
+ case LTC_ASN1_OBJECT_IDENTIFIER:
+ if ((err = der_length_object_identifier(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_IA5_STRING:
+ if ((err = der_length_ia5_string(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_PRINTABLE_STRING:
+ if ((err = der_length_printable_string(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_UTF8_STRING:
+ if ((err = der_length_utf8_string(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_UTCTIME:
+ if ((err = der_length_utctime(data, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_SET:
+ case LTC_ASN1_SETOF:
+ case LTC_ASN1_SEQUENCE:
+ if ((err = der_length_sequence(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ default:
+ err = CRYPT_INVALID_ARG;
+ goto LBL_ERR;
+ }
+ }
+
+ /* calc header size */
+ z = y;
+ if (y < 128) {
+ y += 2;
+ } else if (y < 256) {
+ /* 0x30 0x81 LL */
+ y += 3;
+ } else if (y < 65536UL) {
+ /* 0x30 0x82 LL LL */
+ y += 4;
+ } else if (y < 16777216UL) {
+ /* 0x30 0x83 LL LL LL */
+ y += 5;
+ } else {
+ err = CRYPT_INVALID_ARG;
+ goto LBL_ERR;
+ }
+
+ /* too big ? */
+ if (*outlen < y) {
+ *outlen = y;
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto LBL_ERR;
+ }
+
+ /* store header */
+ x = 0;
+ out[x++] = (type_of == LTC_ASN1_SEQUENCE) ? 0x30 : 0x31;
+
+ if (z < 128) {
+ out[x++] = (unsigned char)z;
+ } else if (z < 256) {
+ out[x++] = 0x81;
+ out[x++] = (unsigned char)z;
+ } else if (z < 65536UL) {
+ out[x++] = 0x82;
+ out[x++] = (unsigned char)((z>>8UL)&255);
+ out[x++] = (unsigned char)(z&255);
+ } else if (z < 16777216UL) {
+ out[x++] = 0x83;
+ out[x++] = (unsigned char)((z>>16UL)&255);
+ out[x++] = (unsigned char)((z>>8UL)&255);
+ out[x++] = (unsigned char)(z&255);
+ }
+
+ /* store data */
+ *outlen -= x;
+ for (i = 0; i < inlen; i++) {
+ type = list[i].type;
+ size = list[i].size;
+ data = list[i].data;
+
+ if (type == LTC_ASN1_EOL) {
+ break;
+ }
+
+ switch (type) {
+ case LTC_ASN1_BOOLEAN:
+ z = *outlen;
+ if ((err = der_encode_boolean(*((int *)data), out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += z;
+ *outlen -= z;
+ break;
+
+ case LTC_ASN1_INTEGER:
+ z = *outlen;
+ if ((err = der_encode_integer(data, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += z;
+ *outlen -= z;
+ break;
+
+ case LTC_ASN1_SHORT_INTEGER:
+ z = *outlen;
+ if ((err = der_encode_short_integer(*((unsigned long*)data), out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += z;
+ *outlen -= z;
+ break;
+
+ case LTC_ASN1_BIT_STRING:
+ z = *outlen;
+ if ((err = der_encode_bit_string(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += z;
+ *outlen -= z;
+ break;
+
+ case LTC_ASN1_OCTET_STRING:
+ z = *outlen;
+ if ((err = der_encode_octet_string(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += z;
+ *outlen -= z;
+ break;
+
+ case LTC_ASN1_NULL:
+ out[x++] = 0x05;
+ out[x++] = 0x00;
+ *outlen -= 2;
+ break;
+
+ case LTC_ASN1_OBJECT_IDENTIFIER:
+ z = *outlen;
+ if ((err = der_encode_object_identifier(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += z;
+ *outlen -= z;
+ break;
+
+ case LTC_ASN1_IA5_STRING:
+ z = *outlen;
+ if ((err = der_encode_ia5_string(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += z;
+ *outlen -= z;
+ break;
+
+ case LTC_ASN1_PRINTABLE_STRING:
+ z = *outlen;
+ if ((err = der_encode_printable_string(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += z;
+ *outlen -= z;
+ break;
+
+ case LTC_ASN1_UTF8_STRING:
+ z = *outlen;
+ if ((err = der_encode_utf8_string(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += z;
+ *outlen -= z;
+ break;
+
+ case LTC_ASN1_UTCTIME:
+ z = *outlen;
+ if ((err = der_encode_utctime(data, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += z;
+ *outlen -= z;
+ break;
+
+ case LTC_ASN1_SET:
+ z = *outlen;
+ if ((err = der_encode_set(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += z;
+ *outlen -= z;
+ break;
+
+ case LTC_ASN1_SETOF:
+ z = *outlen;
+ if ((err = der_encode_setof(data, size, out + x, &z)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += z;
+ *outlen -= z;
+ break;
+
+ case LTC_ASN1_SEQUENCE:
+ z = *outlen;
+ if ((err = der_encode_sequence_ex(data, size, out + x, &z, type)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ x += z;
+ *outlen -= z;
+ break;
+
+ default:
+ err = CRYPT_INVALID_ARG;
+ goto LBL_ERR;
+ }
+ }
+ *outlen = x;
+ err = CRYPT_OK;
+
+LBL_ERR:
+ return err;
+}
+
+#endif
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_encode_sequence_multi.c b/crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_encode_sequence_multi.c
new file mode 100644
index 0000000..7e813172
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_encode_sequence_multi.c
@@ -0,0 +1,139 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include <stdarg.h>
+#include <linux/slab.h>
+
+
+/**
+ @file der_encode_sequence_multi.c
+ ASN.1 DER, encode a SEQUENCE, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/**
+ Encode a SEQUENCE type using a VA list
+ @param out [out] Destination for data
+ @param outlen [in/out] Length of buffer and resulting length of output
+ @remark <...> is of the form <type, size, data> (int, unsigned long, void*)
+ @return CRYPT_OK on success
+*/
+int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...)
+{
+ int err, type;
+ unsigned long size, x;
+ void *data;
+ va_list args;
+ ltc_asn1_list *list;
+
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* get size of output that will be required */
+ va_start(args, outlen);
+ x = 0;
+ for (;;) {
+ type = va_arg(args, int);
+ size = va_arg(args, unsigned long);
+ data = va_arg(args, void*);
+
+ if (type == LTC_ASN1_EOL) {
+ break;
+ }
+
+ switch (type) {
+ case LTC_ASN1_BOOLEAN:
+ case LTC_ASN1_INTEGER:
+ case LTC_ASN1_SHORT_INTEGER:
+ case LTC_ASN1_BIT_STRING:
+ case LTC_ASN1_OCTET_STRING:
+ case LTC_ASN1_NULL:
+ case LTC_ASN1_OBJECT_IDENTIFIER:
+ case LTC_ASN1_IA5_STRING:
+ case LTC_ASN1_PRINTABLE_STRING:
+ case LTC_ASN1_UTF8_STRING:
+ case LTC_ASN1_UTCTIME:
+ case LTC_ASN1_SEQUENCE:
+ case LTC_ASN1_SET:
+ case LTC_ASN1_SETOF:
+ ++x;
+ break;
+
+ default:
+ va_end(args);
+ return CRYPT_INVALID_ARG;
+ }
+ }
+ va_end(args);
+
+ /* allocate structure for x elements */
+ if (x == 0) {
+ return CRYPT_NOP;
+ }
+
+ list = XCALLOC(sizeof(*list), x);
+ if (list == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* fill in the structure */
+ va_start(args, outlen);
+ x = 0;
+ for (;;) {
+ type = va_arg(args, int);
+ size = va_arg(args, unsigned long);
+ data = va_arg(args, void*);
+
+ if (type == LTC_ASN1_EOL) {
+ break;
+ }
+
+ switch (type) {
+ case LTC_ASN1_BOOLEAN:
+ case LTC_ASN1_INTEGER:
+ case LTC_ASN1_SHORT_INTEGER:
+ case LTC_ASN1_BIT_STRING:
+ case LTC_ASN1_OCTET_STRING:
+ case LTC_ASN1_NULL:
+ case LTC_ASN1_OBJECT_IDENTIFIER:
+ case LTC_ASN1_IA5_STRING:
+ case LTC_ASN1_PRINTABLE_STRING:
+ case LTC_ASN1_UTF8_STRING:
+ case LTC_ASN1_UTCTIME:
+ case LTC_ASN1_SEQUENCE:
+ case LTC_ASN1_SET:
+ case LTC_ASN1_SETOF:
+ list[x].type = type;
+ list[x].size = size;
+ list[x++].data = data;
+ break;
+
+ default:
+ va_end(args);
+ err = CRYPT_INVALID_ARG;
+ goto LBL_ERR;
+ }
+ }
+ va_end(args);
+
+ err = der_encode_sequence(list, x, out, outlen);
+LBL_ERR:
+ XFREE(list);
+ return err;
+}
+
+#endif
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_multi.c,v $ */
+/* $Revision: 1.12 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_length_sequence.c b/crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_length_sequence.c
new file mode 100644
index 0000000..d2e9803
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_length_sequence.c
@@ -0,0 +1,169 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_length_sequence.c
+ ASN.1 DER, length a SEQUENCE, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/**
+ Get the length of a DER sequence
+ @param list The sequences of items in the SEQUENCE
+ @param inlen The number of items
+ @param outlen [out] The length required in octets to store it
+ @return CRYPT_OK on success
+*/
+int der_length_sequence(ltc_asn1_list *list, unsigned long inlen,
+ unsigned long *outlen)
+{
+ int err, type;
+ unsigned long size, x, y, z, i;
+ void *data;
+
+ LTC_ARGCHK(list != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* get size of output that will be required */
+ y = 0;
+ for (i = 0; i < inlen; i++) {
+ type = list[i].type;
+ size = list[i].size;
+ data = list[i].data;
+
+ if (type == LTC_ASN1_EOL) {
+ break;
+ }
+
+ switch (type) {
+ case LTC_ASN1_BOOLEAN:
+ if ((err = der_length_boolean(&x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_INTEGER:
+ if ((err = der_length_integer(data, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_SHORT_INTEGER:
+ if ((err = der_length_short_integer(*((unsigned long *)data), &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_BIT_STRING:
+ if ((err = der_length_bit_string(size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_OCTET_STRING:
+ if ((err = der_length_octet_string(size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_NULL:
+ y += 2;
+ break;
+
+ case LTC_ASN1_OBJECT_IDENTIFIER:
+ if ((err = der_length_object_identifier(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_IA5_STRING:
+ if ((err = der_length_ia5_string(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_PRINTABLE_STRING:
+ if ((err = der_length_printable_string(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_UTCTIME:
+ if ((err = der_length_utctime(data, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_UTF8_STRING:
+ if ((err = der_length_utf8_string(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+ case LTC_ASN1_SET:
+ case LTC_ASN1_SETOF:
+ case LTC_ASN1_SEQUENCE:
+ if ((err = der_length_sequence(data, size, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ y += x;
+ break;
+
+
+ default:
+ err = CRYPT_INVALID_ARG;
+ goto LBL_ERR;
+ }
+ }
+
+ /* calc header size */
+ z = y;
+ if (y < 128) {
+ y += 2;
+ } else if (y < 256) {
+ /* 0x30 0x81 LL */
+ y += 3;
+ } else if (y < 65536UL) {
+ /* 0x30 0x82 LL LL */
+ y += 4;
+ } else if (y < 16777216UL) {
+ /* 0x30 0x83 LL LL LL */
+ y += 5;
+ } else {
+ err = CRYPT_INVALID_ARG;
+ goto LBL_ERR;
+ }
+
+ /* store size */
+ *outlen = y;
+ err = CRYPT_OK;
+
+LBL_ERR:
+ return err;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/sequence/der_length_sequence.c,v $ */
+/* $Revision: 1.14 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_sequence_free.c b/crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_sequence_free.c
new file mode 100644
index 0000000..eed73e7
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/sequence/der_sequence_free.c
@@ -0,0 +1,66 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include <linux/slab.h>
+
+/**
+ @file der_sequence_free.c
+ ASN.1 DER, free's a structure allocated by der_decode_sequence_flexi(), Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/**
+ Free memory allocated by der_decode_sequence_flexi()
+ @param in The list to free
+*/
+void der_sequence_free(ltc_asn1_list *in)
+{
+ ltc_asn1_list *l;
+
+ /* walk to the start of the chain */
+ while (in->prev != NULL || in->parent != NULL) {
+ if (in->parent != NULL) {
+ in = in->parent;
+ } else {
+ in = in->prev;
+ }
+ }
+
+ /* now walk the list and free stuff */
+ while (in != NULL) {
+ /* is there a child? */
+ if (in->child) {
+ /* disconnect */
+ in->child->parent = NULL;
+ der_sequence_free(in->child);
+ }
+
+ switch (in->type) {
+ case LTC_ASN1_SET:
+ case LTC_ASN1_SETOF:
+ case LTC_ASN1_SEQUENCE: break;
+ case LTC_ASN1_INTEGER : if (in->data != NULL) { mp_clear(in->data); XFREE(in->data); } break;
+ default : if (in->data != NULL) { XFREE(in->data); }
+ }
+
+ /* move to next and free current */
+ l = in->next;
+ XFREE(in);
+ in = l;
+ }
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/sequence/der_sequence_free.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/set/der_encode_set.c b/crypto/userspace/libtomcrypt/pk/asn1/der/set/der_encode_set.c
new file mode 100644
index 0000000..babb9ea
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/set/der_encode_set.c
@@ -0,0 +1,104 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include <linux/slab.h>
+
+/**
+ @file der_encode_set.c
+ ASN.1 DER, Encode a SET, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/* LTC define to ASN.1 TAG */
+static int ltc_to_asn1(int v)
+{
+ switch (v) {
+ case LTC_ASN1_BOOLEAN: return 0x01;
+ case LTC_ASN1_INTEGER:
+ case LTC_ASN1_SHORT_INTEGER: return 0x02;
+ case LTC_ASN1_BIT_STRING: return 0x03;
+ case LTC_ASN1_OCTET_STRING: return 0x04;
+ case LTC_ASN1_NULL: return 0x05;
+ case LTC_ASN1_OBJECT_IDENTIFIER: return 0x06;
+ case LTC_ASN1_UTF8_STRING: return 0x0C;
+ case LTC_ASN1_PRINTABLE_STRING: return 0x13;
+ case LTC_ASN1_IA5_STRING: return 0x16;
+ case LTC_ASN1_UTCTIME: return 0x17;
+ case LTC_ASN1_SEQUENCE: return 0x30;
+ case LTC_ASN1_SET:
+ case LTC_ASN1_SETOF: return 0x31;
+ default: return -1;
+ }
+}
+
+
+static int qsort_helper(const void *a, const void *b)
+{
+ ltc_asn1_list *A = (ltc_asn1_list *)a, *B = (ltc_asn1_list *)b;
+ int r;
+
+ r = ltc_to_asn1(A->type) - ltc_to_asn1(B->type);
+
+ /* for QSORT the order is UNDEFINED if they are "equal" which means it is NOT DETERMINISTIC. So we force it to be :-) */
+ if (r == 0) {
+ /* their order in the original list now determines the position */
+ return A->used - B->used;
+ } else {
+ return r;
+ }
+}
+
+/*
+ Encode a SET type
+ @param list The list of items to encode
+ @param inlen The number of items in the list
+ @param out [out] The destination
+ @param outlen [in/out] The size of the output
+ @return CRYPT_OK on success
+*/
+int der_encode_set(ltc_asn1_list *list, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ ltc_asn1_list *copy;
+ unsigned long x;
+ int err;
+
+ /* make copy of list */
+ copy = XCALLOC(inlen, sizeof(*copy));
+ if (copy == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* fill in used member with index so we can fully sort it */
+ for (x = 0; x < inlen; x++) {
+ copy[x] = list[x];
+ copy[x].used = x;
+ }
+
+ /* sort it by the "type" field */
+ XQSORT(copy, inlen, sizeof(*copy), &qsort_helper);
+
+ /* call der_encode_sequence_ex() */
+ err = der_encode_sequence_ex(copy, inlen, out, outlen, LTC_ASN1_SET);
+
+ /* free list */
+ XFREE(copy);
+
+ return err;
+}
+
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/set/der_encode_set.c,v $ */
+/* $Revision: 1.12 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/set/der_encode_setof.c b/crypto/userspace/libtomcrypt/pk/asn1/der/set/der_encode_setof.c
new file mode 100644
index 0000000..2a343f2
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/set/der_encode_setof.c
@@ -0,0 +1,163 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include <linux/slab.h>
+
+/**
+ @file der_encode_setof.c
+ ASN.1 DER, Encode SET OF, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+struct edge {
+ unsigned char *start;
+ unsigned long size;
+};
+
+static int qsort_helper(const void *a, const void *b)
+{
+ struct edge *A = (struct edge *)a, *B = (struct edge *)b;
+ int r;
+ unsigned long x;
+
+ /* compare min length */
+ r = XMEMCMP(A->start, B->start, MIN(A->size, B->size));
+
+ if (r == 0 && A->size != B->size) {
+ if (A->size > B->size) {
+ for (x = B->size; x < A->size; x++) {
+ if (A->start[x]) {
+ return 1;
+ }
+ }
+ } else {
+ for (x = A->size; x < B->size; x++) {
+ if (B->start[x]) {
+ return -1;
+ }
+ }
+ }
+ }
+
+ return r;
+}
+
+/**
+ Encode a SETOF stucture
+ @param list The list of items to encode
+ @param inlen The number of items in the list
+ @param out [out] The destination
+ @param outlen [in/out] The size of the output
+ @return CRYPT_OK on success
+*/
+int der_encode_setof(ltc_asn1_list *list, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long x, y, z, hdrlen;
+ int err;
+ struct edge *edges;
+ unsigned char *ptr, *buf;
+
+ /* check that they're all the same type */
+ for (x = 1; x < inlen; x++) {
+ if (list[x].type != list[x-1].type) {
+ return CRYPT_INVALID_ARG;
+ }
+ }
+
+ /* alloc buffer to store copy of output */
+ buf = XCALLOC(1, *outlen);
+ if (buf == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* encode list */
+ if ((err = der_encode_sequence_ex(list, inlen, buf, outlen, LTC_ASN1_SETOF)) != CRYPT_OK) {
+ XFREE(buf);
+ return err;
+ }
+
+ /* allocate edges */
+ edges = XCALLOC(inlen, sizeof(*edges));
+ if (edges == NULL) {
+ XFREE(buf);
+ return CRYPT_MEM;
+ }
+
+ /* skip header */
+ ptr = buf + 1;
+
+ /* now skip length data */
+ x = *ptr++;
+ if (x >= 0x80) {
+ ptr += (x & 0x7F);
+ }
+
+ /* get the size of the static header */
+ hdrlen = ((unsigned long)ptr) - ((unsigned long)buf);
+
+
+ /* scan for edges */
+ x = 0;
+ while (ptr < (buf + *outlen)) {
+ /* store start */
+ edges[x].start = ptr;
+
+ /* skip type */
+ z = 1;
+
+ /* parse length */
+ y = ptr[z++];
+ if (y < 128) {
+ edges[x].size = y;
+ } else {
+ y &= 0x7F;
+ edges[x].size = 0;
+ while (y--) {
+ edges[x].size = (edges[x].size << 8) | ((unsigned long)ptr[z++]);
+ }
+ }
+
+ /* skip content */
+ edges[x].size += z;
+ ptr += edges[x].size;
+ ++x;
+ }
+
+ /* sort based on contents (using edges) */
+ XQSORT(edges, inlen, sizeof(*edges), &qsort_helper);
+
+ /* copy static header */
+ XMEMCPY(out, buf, hdrlen);
+
+ /* copy+sort using edges+indecies to output from buffer */
+ for (y = hdrlen, x = 0; x < inlen; x++) {
+ XMEMCPY(out+y, edges[x].start, edges[x].size);
+ y += edges[x].size;
+ }
+
+#ifdef LTC_CLEAN_STACK
+ zeromem(buf, *outlen);
+#endif
+
+ /* free buffers */
+ XFREE(edges);
+ XFREE(buf);
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/set/der_encode_setof.c,v $ */
+/* $Revision: 1.12 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/short_integer/der_decode_short_integer.c b/crypto/userspace/libtomcrypt/pk/asn1/der/short_integer/der_decode_short_integer.c
new file mode 100644
index 0000000..fbb89a4
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/short_integer/der_decode_short_integer.c
@@ -0,0 +1,68 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_decode_short_integer.c
+ ASN.1 DER, decode an integer, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Read a short integer
+ @param in The DER encoded data
+ @param inlen Size of data
+ @param num [out] The integer to decode
+ @return CRYPT_OK if successful
+*/
+int der_decode_short_integer(const unsigned char *in, unsigned long inlen, unsigned long *num)
+{
+ unsigned long len, x, y;
+
+ LTC_ARGCHK(num != NULL);
+ LTC_ARGCHK(in != NULL);
+
+ /* check length */
+ if (inlen < 2) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* check header */
+ x = 0;
+ if ((in[x++] & 0x1F) != 0x02) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* get the packet len */
+ len = in[x++];
+
+ if (x + len > inlen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* read number */
+ y = 0;
+ while (len--) {
+ y = (y<<8) | (unsigned long)in[x++];
+ }
+ *num = y;
+
+ return CRYPT_OK;
+
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/short_integer/der_decode_short_integer.c,v $ */
+/* $Revision: 1.7 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/short_integer/der_encode_short_integer.c b/crypto/userspace/libtomcrypt/pk/asn1/der/short_integer/der_encode_short_integer.c
new file mode 100644
index 0000000..cd9e6d1
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/short_integer/der_encode_short_integer.c
@@ -0,0 +1,97 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_encode_short_integer.c
+ ASN.1 DER, encode an integer, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Store a short integer in the range (0,2^32-1)
+ @param num The integer to encode
+ @param out [out] The destination for the DER encoded integers
+ @param outlen [in/out] The max size and resulting size of the DER encoded integers
+ @return CRYPT_OK if successful
+*/
+int der_encode_short_integer(unsigned long num, unsigned char *out, unsigned long *outlen)
+{
+ unsigned long len, x, y, z;
+ int err;
+
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* force to 32 bits */
+ num &= 0xFFFFFFFFUL;
+
+ /* find out how big this will be */
+ if ((err = der_length_short_integer(num, &len)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (*outlen < len) {
+ *outlen = len;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* get len of output */
+ z = 0;
+ y = num;
+ while (y) {
+ ++z;
+ y >>= 8;
+ }
+
+ /* handle zero */
+ if (z == 0) {
+ z = 1;
+ }
+
+ /* see if msb is set */
+ z += (num&(1UL<<((z<<3) - 1))) ? 1 : 0;
+
+ /* adjust the number so the msB is non-zero */
+ for (x = 0; (z <= 4) && (x < (4 - z)); x++) {
+ num <<= 8;
+ }
+
+ /* store header */
+ x = 0;
+ out[x++] = 0x02;
+ out[x++] = (unsigned char)z;
+
+ /* if 31st bit is set output a leading zero and decrement count */
+ if (z == 5) {
+ out[x++] = 0;
+ --z;
+ }
+
+ /* store values */
+ for (y = 0; y < z; y++) {
+ out[x++] = (unsigned char)((num >> 24) & 0xFF);
+ num <<= 8;
+ }
+
+ /* we good */
+ *outlen = x;
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/short_integer/der_encode_short_integer.c,v $ */
+/* $Revision: 1.8 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/short_integer/der_length_short_integer.c b/crypto/userspace/libtomcrypt/pk/asn1/der/short_integer/der_length_short_integer.c
new file mode 100644
index 0000000..ec3f8f1
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/short_integer/der_length_short_integer.c
@@ -0,0 +1,70 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_length_short_integer.c
+ ASN.1 DER, get length of encoding, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+/**
+ Gets length of DER encoding of num
+ @param num The integer to get the size of
+ @param outlen [out] The length of the DER encoding for the given integer
+ @return CRYPT_OK if successful
+*/
+int der_length_short_integer(unsigned long num, unsigned long *outlen)
+{
+ unsigned long z, y, len;
+
+ LTC_ARGCHK(outlen != NULL);
+
+ /* force to 32 bits */
+ num &= 0xFFFFFFFFUL;
+
+ /* get the number of bytes */
+ z = 0;
+ y = num;
+ while (y) {
+ ++z;
+ y >>= 8;
+ }
+
+ /* handle zero */
+ if (z == 0) {
+ z = 1;
+ }
+
+ /* we need a 0x02 to indicate it's INTEGER */
+ len = 1;
+
+ /* length byte */
+ ++len;
+
+ /* bytes in value */
+ len += z;
+
+ /* see if msb is set */
+ len += (num&(1UL<<((z<<3) - 1))) ? 1 : 0;
+
+ /* return length */
+ *outlen = len;
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/short_integer/der_length_short_integer.c,v $ */
+/* $Revision: 1.6 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/utctime/der_decode_utctime.c b/crypto/userspace/libtomcrypt/pk/asn1/der/utctime/der_decode_utctime.c
new file mode 100644
index 0000000..54fc204
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/utctime/der_decode_utctime.c
@@ -0,0 +1,127 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_decode_utctime.c
+ ASN.1 DER, decode a UTCTIME, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+static int char_to_int(unsigned char x)
+{
+ switch (x) {
+ case '0': return 0;
+ case '1': return 1;
+ case '2': return 2;
+ case '3': return 3;
+ case '4': return 4;
+ case '5': return 5;
+ case '6': return 6;
+ case '7': return 7;
+ case '8': return 8;
+ case '9': return 9;
+ }
+ return 100;
+}
+
+#define DECODE_V(y, max) \
+ y = char_to_int(buf[x])*10 + char_to_int(buf[x+1]); \
+ if (y >= max) return CRYPT_INVALID_PACKET; \
+ x += 2;
+
+/**
+ Decodes a UTC time structure in DER format (reads all 6 valid encoding formats)
+ @param in Input buffer
+ @param inlen Length of input buffer in octets
+ @param out [out] Destination of UTC time structure
+ @return CRYPT_OK if successful
+*/
+int der_decode_utctime(const unsigned char *in, unsigned long *inlen,
+ ltc_utctime *out)
+{
+ unsigned char buf[32];
+ unsigned long x;
+ int y;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(inlen != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ /* check header */
+ if (*inlen < 2UL || (in[1] >= sizeof(buf)) || ((in[1] + 2UL) > *inlen)) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* decode the string */
+ for (x = 0; x < in[1]; x++) {
+ y = der_ia5_value_decode(in[x+2]);
+ if (y == -1) {
+ return CRYPT_INVALID_PACKET;
+ }
+ buf[x] = y;
+ }
+ *inlen = 2 + x;
+
+
+ /* possible encodings are
+YYMMDDhhmmZ
+YYMMDDhhmm+hh'mm'
+YYMMDDhhmm-hh'mm'
+YYMMDDhhmmssZ
+YYMMDDhhmmss+hh'mm'
+YYMMDDhhmmss-hh'mm'
+
+ So let's do a trivial decode upto [including] mm
+ */
+
+ x = 0;
+ DECODE_V(out->YY, 100);
+ DECODE_V(out->MM, 13);
+ DECODE_V(out->DD, 32);
+ DECODE_V(out->hh, 24);
+ DECODE_V(out->mm, 60);
+
+ /* clear timezone and seconds info */
+ out->off_dir = out->off_hh = out->off_mm = out->ss = 0;
+
+ /* now is it Z, +, - or 0-9 */
+ if (buf[x] == 'Z') {
+ return CRYPT_OK;
+ } else if (buf[x] == '+' || buf[x] == '-') {
+ out->off_dir = (buf[x++] == '+') ? 0 : 1;
+ DECODE_V(out->off_hh, 24);
+ DECODE_V(out->off_mm, 60);
+ return CRYPT_OK;
+ }
+
+ /* decode seconds */
+ DECODE_V(out->ss, 60);
+
+ /* now is it Z, +, - */
+ if (buf[x] == 'Z') {
+ return CRYPT_OK;
+ } else if (buf[x] == '+' || buf[x] == '-') {
+ out->off_dir = (buf[x++] == '+') ? 0 : 1;
+ DECODE_V(out->off_hh, 24);
+ DECODE_V(out->off_mm, 60);
+ return CRYPT_OK;
+ } else {
+ return CRYPT_INVALID_PACKET;
+ }
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/utctime/der_decode_utctime.c,v $ */
+/* $Revision: 1.9 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/utctime/der_encode_utctime.c b/crypto/userspace/libtomcrypt/pk/asn1/der/utctime/der_encode_utctime.c
new file mode 100644
index 0000000..cb32dfa
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/utctime/der_encode_utctime.c
@@ -0,0 +1,83 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_encode_utctime.c
+ ASN.1 DER, encode a UTCTIME, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+static const char *baseten = "0123456789";
+
+#define STORE_V(y) \
+ out[x++] = der_ia5_char_encode(baseten[(y/10) % 10]); \
+ out[x++] = der_ia5_char_encode(baseten[y % 10]);
+
+/**
+ Encodes a UTC time structure in DER format
+ @param utctime The UTC time structure to encode
+ @param out The destination of the DER encoding of the UTC time structure
+ @param outlen [in/out] The length of the DER encoding
+ @return CRYPT_OK if successful
+*/
+int der_encode_utctime(ltc_utctime *utctime,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long x, tmplen;
+ int err;
+
+ LTC_ARGCHK(utctime != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ if ((err = der_length_utctime(utctime, &tmplen)) != CRYPT_OK) {
+ return err;
+ }
+ if (tmplen > *outlen) {
+ *outlen = tmplen;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* store header */
+ out[0] = 0x17;
+
+ /* store values */
+ x = 2;
+ STORE_V(utctime->YY);
+ STORE_V(utctime->MM);
+ STORE_V(utctime->DD);
+ STORE_V(utctime->hh);
+ STORE_V(utctime->mm);
+ STORE_V(utctime->ss);
+
+ if (utctime->off_mm || utctime->off_hh) {
+ out[x++] = der_ia5_char_encode(utctime->off_dir ? '-' : '+');
+ STORE_V(utctime->off_hh);
+ STORE_V(utctime->off_mm);
+ } else {
+ out[x++] = der_ia5_char_encode('Z');
+ }
+
+ /* store length */
+ out[1] = (unsigned char)(x - 2);
+
+ /* all good let's return */
+ *outlen = x;
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/utctime/der_encode_utctime.c,v $ */
+/* $Revision: 1.10 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/utctime/der_length_utctime.c b/crypto/userspace/libtomcrypt/pk/asn1/der/utctime/der_length_utctime.c
new file mode 100644
index 0000000..e5922b0
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/utctime/der_length_utctime.c
@@ -0,0 +1,46 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_length_utctime.c
+ ASN.1 DER, get length of UTCTIME, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/**
+ Gets length of DER encoding of UTCTIME
+ @param utctime The UTC time structure to get the size of
+ @param outlen [out] The length of the DER encoding
+ @return CRYPT_OK if successful
+*/
+int der_length_utctime(ltc_utctime *utctime, unsigned long *outlen)
+{
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(utctime != NULL);
+
+ if (utctime->off_hh == 0 && utctime->off_mm == 0) {
+ /* we encode as YYMMDDhhmmssZ */
+ *outlen = 2 + 13;
+ } else {
+ /* we encode as YYMMDDhhmmss{+|-}hh'mm' */
+ *outlen = 2 + 17;
+ }
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/utctime/der_length_utctime.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/utf8/der_decode_utf8_string.c b/crypto/userspace/libtomcrypt/pk/asn1/der/utf8/der_decode_utf8_string.c
new file mode 100644
index 0000000..9df7e23
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/utf8/der_decode_utf8_string.c
@@ -0,0 +1,111 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_decode_utf8_string.c
+ ASN.1 DER, encode a UTF8 STRING, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Store a UTF8 STRING
+ @param in The DER encoded UTF8 STRING
+ @param inlen The size of the DER UTF8 STRING
+ @param out [out] The array of utf8s stored (one per char)
+ @param outlen [in/out] The number of utf8s stored
+ @return CRYPT_OK if successful
+*/
+int der_decode_utf8_string(const unsigned char *in, unsigned long inlen,
+ wchar_t *out, unsigned long *outlen)
+{
+ wchar_t tmp;
+ unsigned long x, y, z, len;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* must have header at least */
+ if (inlen < 2) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* check for 0x0C */
+ if ((in[0] & 0x1F) != 0x0C) {
+ return CRYPT_INVALID_PACKET;
+ }
+ x = 1;
+
+ /* decode the length */
+ if (in[x] & 0x80) {
+ /* valid # of bytes in length are 1,2,3 */
+ y = in[x] & 0x7F;
+ if ((y == 0) || (y > 3) || ((x + y) > inlen)) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* read the length in */
+ len = 0;
+ ++x;
+ while (y--) {
+ len = (len << 8) | in[x++];
+ }
+ } else {
+ len = in[x++] & 0x7F;
+ }
+
+ if (len + x > inlen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* proceed to decode */
+ for (y = 0; x < inlen; ) {
+ /* get first byte */
+ tmp = in[x++];
+
+ /* count number of bytes */
+ for (z = 0; (tmp & 0x80) && (z <= 4); z++, tmp = (tmp << 1) & 0xFF);
+
+ if (z > 4 || (x + (z - 1) > inlen)) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* decode, grab upper bits */
+ tmp >>= z;
+
+ /* grab remaining bytes */
+ if (z > 1) { --z; }
+ while (z-- != 0) {
+ if ((in[x] & 0xC0) != 0x80) {
+ return CRYPT_INVALID_PACKET;
+ }
+ tmp = (tmp << 6) | ((wchar_t)in[x++] & 0x3F);
+ }
+
+ if (y > *outlen) {
+ *outlen = y;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+ out[y++] = tmp;
+ }
+ *outlen = y;
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/utf8/der_decode_utf8_string.c,v $ */
+/* $Revision: 1.8 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/utf8/der_encode_utf8_string.c b/crypto/userspace/libtomcrypt/pk/asn1/der/utf8/der_encode_utf8_string.c
new file mode 100644
index 0000000..d1efb09
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/utf8/der_encode_utf8_string.c
@@ -0,0 +1,105 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_encode_utf8_string.c
+ ASN.1 DER, encode a UTF8 STRING, Tom St Denis
+*/
+
+
+#ifdef LTC_DER
+
+/**
+ Store an UTF8 STRING
+ @param in The array of UTF8 to store (one per wchar_t)
+ @param inlen The number of UTF8 to store
+ @param out [out] The destination for the DER encoded UTF8 STRING
+ @param outlen [in/out] The max size and resulting size of the DER UTF8 STRING
+ @return CRYPT_OK if successful
+*/
+int der_encode_utf8_string(const wchar_t *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long x, y, len;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* get the size */
+ for (x = len = 0; x < inlen; x++) {
+ if (in[x] < 0 || in[x] > 0x1FFFF) {
+ return CRYPT_INVALID_ARG;
+ }
+ len += der_utf8_charsize(in[x]);
+ }
+
+ if (len < 128) {
+ y = 2 + len;
+ } else if (len < 256) {
+ y = 3 + len;
+ } else if (len < 65536UL) {
+ y = 4 + len;
+ } else if (len < 16777216UL) {
+ y = 5 + len;
+ } else {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* too big? */
+ if (y > *outlen) {
+ *outlen = len;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* encode the header+len */
+ x = 0;
+ out[x++] = 0x0C;
+ if (len < 128) {
+ out[x++] = (unsigned char)len;
+ } else if (len < 256) {
+ out[x++] = 0x81;
+ out[x++] = (unsigned char)len;
+ } else if (len < 65536UL) {
+ out[x++] = 0x82;
+ out[x++] = (unsigned char)((len>>8)&255);
+ out[x++] = (unsigned char)(len&255);
+ } else if (len < 16777216UL) {
+ out[x++] = 0x83;
+ out[x++] = (unsigned char)((len>>16)&255);
+ out[x++] = (unsigned char)((len>>8)&255);
+ out[x++] = (unsigned char)(len&255);
+ } else {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* store UTF8 */
+ for (y = 0; y < inlen; y++) {
+ switch (der_utf8_charsize(in[y])) {
+ case 1: out[x++] = (unsigned char)in[y]; break;
+ case 2: out[x++] = 0xC0 | ((in[y] >> 6) & 0x1F); out[x++] = 0x80 | (in[y] & 0x3F); break;
+ case 3: out[x++] = 0xE0 | ((in[y] >> 12) & 0x0F); out[x++] = 0x80 | ((in[y] >> 6) & 0x3F); out[x++] = 0x80 | (in[y] & 0x3F); break;
+ case 4: out[x++] = 0xF0 | ((in[y] >> 18) & 0x07); out[x++] = 0x80 | ((in[y] >> 12) & 0x3F); out[x++] = 0x80 | ((in[y] >> 6) & 0x3F); out[x++] = 0x80 | (in[y] & 0x3F); break;
+ }
+ }
+
+ /* retun length */
+ *outlen = x;
+
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/utf8/der_encode_utf8_string.c,v $ */
+/* $Revision: 1.9 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/utf8/der_length_utf8_string.c b/crypto/userspace/libtomcrypt/pk/asn1/der/utf8/der_length_utf8_string.c
new file mode 100644
index 0000000..920bd00
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/utf8/der_length_utf8_string.c
@@ -0,0 +1,83 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_length_utf8_string.c
+ ASN.1 DER, get length of UTF8 STRING, Tom St Denis
+*/
+
+#ifdef LTC_DER
+
+/** Return the size in bytes of a UTF-8 character
+ @param c The UTF-8 character to measure
+ @return The size in bytes
+*/
+unsigned long der_utf8_charsize(const wchar_t c)
+{
+ if (c <= 0x7F) {
+ return 1;
+ } else if (c <= 0x7FF) {
+ return 2;
+ } else if (c <= 0xFFFF) {
+ return 3;
+ } else {
+ return 4;
+ }
+}
+
+/**
+ Gets length of DER encoding of UTF8 STRING
+ @param in The characters to measure the length of
+ @param noctets The number of octets in the string to encode
+ @param outlen [out] The length of the DER encoding for the given string
+ @return CRYPT_OK if successful
+*/
+int der_length_utf8_string(const wchar_t *in, unsigned long noctets, unsigned long *outlen)
+{
+ unsigned long x, len;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ len = 0;
+ for (x = 0; x < noctets; x++) {
+ if (in[x] < 0 || in[x] > 0x10FFFF) {
+ return CRYPT_INVALID_ARG;
+ }
+ len += der_utf8_charsize(in[x]);
+ }
+
+ if (len < 128) {
+ /* 0C LL DD DD DD ... */
+ *outlen = 2 + len;
+ } else if (len < 256) {
+ /* 0C 81 LL DD DD DD ... */
+ *outlen = 3 + len;
+ } else if (len < 65536UL) {
+ /* 0C 82 LL LL DD DD DD ... */
+ *outlen = 4 + len;
+ } else if (len < 16777216UL) {
+ /* 0C 83 LL LL LL DD DD DD ... */
+ *outlen = 5 + len;
+ } else {
+ return CRYPT_INVALID_ARG;
+ }
+
+ return CRYPT_OK;
+}
+
+#endif
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/utf8/der_length_utf8_string.c,v $ */
+/* $Revision: 1.6 $ */
+/* $Date: 2006/12/28 01:27:24 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/x509/der_decode_subject_public_key_info.c b/crypto/userspace/libtomcrypt/pk/asn1/der/x509/der_decode_subject_public_key_info.c
new file mode 100644
index 0000000..8a5005f
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/x509/der_decode_subject_public_key_info.c
@@ -0,0 +1,112 @@
+/*
+ * New driver for /dev/crypto device (aka CryptoDev)
+
+ * Copyright (c) 2010 Katholieke Universiteit Leuven
+ *
+ * Author: Nikos Mavrogiannopoulos <[email protected]>
+ *
+ * This file is part of linux cryptodev.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#include "tomcrypt.h"
+#include <linux/slab.h>
+/**
+ @file der_encode_sequence_multi.c
+ ASN.1 DER, encode a Subject Public Key structure --nmav
+*/
+
+#ifdef LTC_DER
+
+/* AlgorithmIdentifier := SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm
+ * }
+ *
+ * SubjectPublicKeyInfo := SEQUENCE {
+ * algorithm AlgorithmIdentifier,
+ * subjectPublicKey BIT STRING
+ * }
+ */
+/**
+ Encode a SEQUENCE type using a VA list
+ @param out [out] Destination for data
+ @param outlen [in/out] Length of buffer and resulting length of output
+ @remark <...> is of the form <type, size, data> (int, unsigned long, void*)
+ @return CRYPT_OK on success
+*/
+int der_decode_subject_public_key_info(const unsigned char *in, unsigned long inlen,
+ unsigned int algorithm, void* public_key, unsigned long* public_key_len,
+ unsigned long parameters_type, ltc_asn1_list* parameters, unsigned long parameters_len)
+{
+ int err, len;
+ oid_st oid;
+ unsigned char *tmpbuf;
+ unsigned long tmpoid[16];
+ ltc_asn1_list alg_id[2];
+ ltc_asn1_list subject_pubkey[2];
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(inlen != 0);
+
+ err = pk_get_oid(algorithm, &oid);
+ if (err != CRYPT_OK) {
+ return err;
+ }
+
+ /* see if the OpenSSL DER format RSA public key will work */
+ tmpbuf = XCALLOC(1, MAX_RSA_SIZE*8);
+ if (tmpbuf == NULL) {
+ err = CRYPT_MEM;
+ goto LBL_ERR;
+ }
+
+ /* this includes the internal hash ID and optional params (NULL in this case) */
+ LTC_SET_ASN1(alg_id, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, sizeof(tmpoid)/sizeof(tmpoid[0]));
+ LTC_SET_ASN1(alg_id, 1, parameters_type, parameters, parameters_len);
+
+ /* the actual format of the SSL DER key is odd, it stores a RSAPublicKey in a **BIT** string ... so we have to extract it
+ then proceed to convert bit to octet
+ */
+ LTC_SET_ASN1(subject_pubkey, 0, LTC_ASN1_SEQUENCE, alg_id, 2);
+ LTC_SET_ASN1(subject_pubkey, 1, LTC_ASN1_BIT_STRING, tmpbuf, MAX_RSA_SIZE*8);
+
+ err=der_decode_sequence(in, inlen, subject_pubkey, 2UL);
+ if (err != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ len = subject_pubkey[1].size/8;
+ if (*public_key_len > len) {
+ memcpy(public_key, subject_pubkey[1].data, len);
+ *public_key_len = len;
+ } else {
+ *public_key_len = len;
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto LBL_ERR;
+ }
+
+ err = CRYPT_OK;
+
+LBL_ERR:
+
+ XFREE(tmpbuf);
+
+ return err;
+}
+
+#endif
+
+
diff --git a/crypto/userspace/libtomcrypt/pk/asn1/der/x509/der_encode_subject_public_key_info.c b/crypto/userspace/libtomcrypt/pk/asn1/der/x509/der_encode_subject_public_key_info.c
new file mode 100644
index 0000000..4c7e966
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/asn1/der/x509/der_encode_subject_public_key_info.c
@@ -0,0 +1,83 @@
+/*
+ * New driver for /dev/crypto device (aka CryptoDev)
+
+ * Copyright (c) 2010 Katholieke Universiteit Leuven
+ *
+ * Author: Nikos Mavrogiannopoulos <[email protected]>
+ *
+ * This file is part of linux cryptodev.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#include "tomcrypt.h"
+
+/**
+ @file der_encode_sequence_multi.c
+ ASN.1 DER, encode a Subject Public Key structure --nmav
+*/
+
+#ifdef LTC_DER
+
+/* AlgorithmIdentifier := SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm
+ * }
+ *
+ * SubjectPublicKeyInfo := SEQUENCE {
+ * algorithm AlgorithmIdentifier,
+ * subjectPublicKey BIT STRING
+ * }
+ */
+/**
+ Encode a SEQUENCE type using a VA list
+ @param out [out] Destination for data
+ @param outlen [in/out] Length of buffer and resulting length of output
+ @remark <...> is of the form <type, size, data> (int, unsigned long, void*)
+ @return CRYPT_OK on success
+*/
+int der_encode_subject_public_key_info(unsigned char *out, unsigned long *outlen,
+ unsigned int algorithm, void* public_key, unsigned long public_key_len,
+ unsigned long parameters_type, void* parameters, unsigned long parameters_len)
+{
+ int err;
+ ltc_asn1_list alg_id[2];
+ oid_st oid;
+
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ err = pk_get_oid(algorithm, &oid);
+ if (err != CRYPT_OK) {
+ return err;
+ }
+
+ alg_id[0].data = oid.OID;
+ alg_id[0].size = oid.OIDlen;
+ alg_id[0].type = LTC_ASN1_OBJECT_IDENTIFIER;
+
+ alg_id[1].data = parameters;
+ alg_id[1].size = parameters_len;
+ alg_id[1].type = parameters_type;
+
+ return der_encode_sequence_multi(out, outlen,
+ LTC_ASN1_SEQUENCE, (unsigned long)sizeof(alg_id)/sizeof(alg_id[0]), alg_id,
+ LTC_ASN1_BIT_STRING, (unsigned long)(public_key_len*8), public_key,
+ LTC_ASN1_EOL, 0UL, NULL);
+
+}
+
+#endif
+
+
diff --git a/crypto/userspace/libtomcrypt/pk/dsa/dsa_export.c b/crypto/userspace/libtomcrypt/pk/dsa/dsa_export.c
new file mode 100644
index 0000000..f2cd714
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/dsa/dsa_export.c
@@ -0,0 +1,99 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include <linux/slab.h>
+
+/**
+ @file dsa_export.c
+ DSA implementation, export key, Tom St Denis
+*/
+
+#ifdef LTC_MDSA
+
+/**
+ Export a DSA key to a binary packet
+ @param out [out] Where to store the packet
+ @param outlen [in/out] The max size and resulting size of the packet
+ @param type The type of key to export (PK_PRIVATE or PK_PUBLIC)
+ @param key The key to export
+ @return CRYPT_OK if successful
+*/
+int dsa_export(unsigned char *out, unsigned long *outlen, int type, dsa_key *key)
+{
+ unsigned long zero=0;
+ int err;
+
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* can we store the static header? */
+ if (type == PK_PRIVATE && key->type != PK_PRIVATE) {
+ return CRYPT_PK_TYPE_MISMATCH;
+ }
+
+ if (type != PK_PUBLIC && type != PK_PRIVATE) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* This encoding is different from the one in original
+ * libtomcrypt. It uses a compatible encoding with gnutls
+ * and openssl
+ */
+ if (type == PK_PRIVATE) {
+ return der_encode_sequence_multi(out, outlen,
+ LTC_ASN1_SHORT_INTEGER, 1UL, &zero,
+ LTC_ASN1_INTEGER, 1UL, &key->p,
+ LTC_ASN1_INTEGER, 1UL, &key->q,
+ LTC_ASN1_INTEGER, 1UL, &key->g,
+ LTC_ASN1_INTEGER, 1UL, &key->y,
+ LTC_ASN1_INTEGER, 1UL, &key->x,
+ LTC_ASN1_EOL, 0UL, NULL);
+ } else {
+ unsigned long tmplen = (mp_count_bits(&key->y)/8)+8;
+ unsigned char* tmp = XMALLOC(tmplen);
+ ltc_asn1_list int_list[3];
+
+ if (tmp == NULL) {
+ return CRYPT_MEM;
+ }
+
+ err = der_encode_integer(&key->y, tmp, &tmplen);
+ if (err != CRYPT_OK) {
+ goto error;
+ }
+
+ int_list[0].data = &key->p;
+ int_list[0].size = 1UL;
+ int_list[0].type = LTC_ASN1_INTEGER;
+ int_list[1].data = &key->q;
+ int_list[1].size = 1UL;
+ int_list[1].type = LTC_ASN1_INTEGER;
+ int_list[2].data = &key->g;
+ int_list[2].size = 1UL;
+ int_list[2].type = LTC_ASN1_INTEGER;
+
+ err = der_encode_subject_public_key_info(out, outlen,
+ PKA_DSA, tmp, tmplen,
+ LTC_ASN1_SEQUENCE, int_list, sizeof(int_list)/sizeof(int_list[0]));
+
+error:
+ XFREE(tmp);
+ return err;
+ }
+}
+
+#endif
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/dsa/dsa_export.c,v $ */
+/* $Revision: 1.10 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/dsa/dsa_free.c b/crypto/userspace/libtomcrypt/pk/dsa/dsa_free.c
new file mode 100644
index 0000000..37a330d
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/dsa/dsa_free.c
@@ -0,0 +1,34 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file dsa_free.c
+ DSA implementation, free a DSA key, Tom St Denis
+*/
+
+#ifdef LTC_MDSA
+
+/**
+ Free a DSA key
+ @param key The key to free from memory
+*/
+void dsa_free(dsa_key *key)
+{
+ LTC_ARGCHKVD(key != NULL);
+ mp_clear_multi(&key->g, &key->q, &key->p, &key->x, &key->y, NULL);
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/dsa/dsa_free.c,v $ */
+/* $Revision: 1.8 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/dsa/dsa_import.c b/crypto/userspace/libtomcrypt/pk/dsa/dsa_import.c
new file mode 100644
index 0000000..99001f2
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/dsa/dsa_import.c
@@ -0,0 +1,101 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include <linux/slab.h>
+
+/**
+ @file dsa_import.c
+ DSA implementation, import a DSA key, Tom St Denis
+*/
+
+#ifdef LTC_MDSA
+
+/**
+ Import a DSA key
+ @param in The binary packet to import from
+ @param inlen The length of the binary packet
+ @param key [out] Where to store the imported key
+ @return CRYPT_OK if successful, upon error this function will free all allocated memory
+*/
+int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key)
+{
+ int err;
+ unsigned long zero = 0;
+ unsigned char* tmpbuf = NULL;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* init key */
+ if (mp_init_multi(&key->p, &key->g, &key->q, &key->x, &key->y, NULL) != CRYPT_OK) {
+ return CRYPT_MEM;
+ }
+
+ /* get key type */
+ if ((err = der_decode_sequence_multi(in, inlen,
+ LTC_ASN1_SHORT_INTEGER, 1UL, &zero,
+ LTC_ASN1_INTEGER, 1UL, &key->p,
+ LTC_ASN1_INTEGER, 1UL, &key->q,
+ LTC_ASN1_INTEGER, 1UL, &key->g,
+ LTC_ASN1_INTEGER, 1UL, &key->y,
+ LTC_ASN1_INTEGER, 1UL, &key->x,
+ LTC_ASN1_EOL, 0UL, NULL)) == CRYPT_OK) {
+ key->type = PK_PRIVATE;
+ } else { /* public */
+ ltc_asn1_list params[3];
+ unsigned long tmpbuf_len = MAX_RSA_SIZE*8;
+
+ LTC_SET_ASN1(params, 0, LTC_ASN1_INTEGER, &key->p, 1UL);
+ LTC_SET_ASN1(params, 1, LTC_ASN1_INTEGER, &key->q, 1UL);
+ LTC_SET_ASN1(params, 2, LTC_ASN1_INTEGER, &key->g, 1UL);
+
+ tmpbuf = XCALLOC(1, tmpbuf_len);
+ if (tmpbuf == NULL) {
+ err = CRYPT_MEM;
+ goto LBL_ERR;
+ }
+
+ err = der_decode_subject_public_key_info(in, inlen,
+ PKA_DSA, tmpbuf, &tmpbuf_len,
+ LTC_ASN1_SEQUENCE, params, 3);
+ if (err != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ if ((err=der_decode_integer(tmpbuf, tmpbuf_len, &key->y)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ XFREE(tmpbuf);
+ key->type = PK_PUBLIC;
+ }
+
+ key->qord = mp_unsigned_bin_size(&key->q);
+
+ if (key->qord >= LTC_MDSA_MAX_GROUP || key->qord <= 15 ||
+ (unsigned long)key->qord >= mp_unsigned_bin_size(&key->p) || (mp_unsigned_bin_size(&key->p) - key->qord) >= LTC_MDSA_DELTA) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+
+ return CRYPT_OK;
+
+LBL_ERR:
+ XFREE(tmpbuf);
+ mp_clear_multi(&key->p, &key->g, &key->q, &key->x, &key->y, NULL);
+ return err;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/dsa/dsa_import.c,v $ */
+/* $Revision: 1.14 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/dsa/dsa_make_key.c b/crypto/userspace/libtomcrypt/pk/dsa/dsa_make_key.c
new file mode 100644
index 0000000..1831853
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/dsa/dsa_make_key.c
@@ -0,0 +1,125 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include <linux/slab.h>
+
+/**
+ @file dsa_make_key.c
+ DSA implementation, generate a DSA key, Tom St Denis
+*/
+
+#ifdef LTC_MDSA
+
+/**
+ Create a DSA key
+ @param group_size Size of the multiplicative group (octets)
+ @param modulus_size Size of the modulus (octets)
+ @param key [out] Where to store the created key
+ @return CRYPT_OK if successful, upon error this function will free all allocated memory
+*/
+int dsa_make_key(int group_size, int modulus_size, dsa_key *key)
+{
+ mp_int tmp, tmp2;
+ int err, res;
+ unsigned char *buf;
+
+ LTC_ARGCHK(key != NULL);
+
+ /* check size */
+ if (group_size >= LTC_MDSA_MAX_GROUP || group_size <= 15 ||
+ group_size >= modulus_size || (modulus_size - group_size) >= LTC_MDSA_DELTA) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* allocate ram */
+ buf = XMALLOC(LTC_MDSA_DELTA);
+ if (buf == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* init mp_ints */
+ if ((err = mp_init_multi(&tmp, &tmp2, &key->g, &key->q, &key->p, &key->x, &key->y, NULL)) != CRYPT_OK) {
+ XFREE(buf);
+ return err;
+ }
+
+ /* make our prime q */
+ if ((err = rand_prime(&key->q, group_size)) != CRYPT_OK) { goto error; }
+
+ /* double q */
+ if ((err = mp_add(&key->q, &key->q, &tmp)) != CRYPT_OK) { goto error; }
+
+ /* now make a random string and multply it against q */
+ get_random_bytes(buf+1, modulus_size - group_size);
+
+ /* force magnitude */
+ buf[0] |= 0xC0;
+
+ /* force even */
+ buf[modulus_size - group_size - 1] &= ~1;
+
+ if ((err = mp_read_unsigned_bin(&tmp2, buf, modulus_size - group_size)) != CRYPT_OK) { goto error; }
+ if ((err = mp_mul(&key->q, &tmp2, &key->p)) != CRYPT_OK) { goto error; }
+ if ((err = mp_add_d(&key->p, 1, &key->p)) != CRYPT_OK) { goto error; }
+
+ /* now loop until p is prime */
+ for (;;) {
+ if ((err = mp_prime_is_prime(&key->p, 8, &res)) != CRYPT_OK) { goto error; }
+ if (res == LTC_MP_YES) break;
+
+ /* add 2q to p and 2 to tmp2 */
+ if ((err = mp_add(&tmp, &key->p, &key->p)) != CRYPT_OK) { goto error; }
+ if ((err = mp_add_d(&tmp2, 2, &tmp2)) != CRYPT_OK) { goto error; }
+ }
+
+ /* now p = (q * tmp2) + 1 is prime, find a value g for which g^tmp2 != 1 */
+ mp_set(&key->g, 1);
+
+ do {
+ if ((err = mp_add_d(&key->g, 1, &key->g)) != CRYPT_OK) { goto error; }
+ if ((err = mp_exptmod(&key->g, &tmp2, &key->p, &tmp)) != CRYPT_OK) { goto error; }
+ } while (mp_cmp_d(&tmp, 1) == LTC_MP_EQ);
+
+ /* at this point tmp generates a group of order q mod p */
+ mp_exch(&tmp, &key->g);
+
+ /* so now we have our DH structure, generator g, order q, modulus p
+ Now we need a random exponent [mod q] and it's power g^x mod p
+ */
+ do {
+ get_random_bytes(buf, group_size);
+
+ if ((err = mp_read_unsigned_bin(&key->x, buf, group_size)) != CRYPT_OK) { goto error; }
+ } while (mp_cmp_d(&key->x, 1) != LTC_MP_GT);
+ if ((err = mp_exptmod(&key->g, &key->x, &key->p, &key->y)) != CRYPT_OK) { goto error; }
+
+ key->type = PK_PRIVATE;
+ key->qord = group_size;
+
+#ifdef LTC_CLEAN_STACK
+ zeromem(buf, LTC_MDSA_DELTA);
+#endif
+
+ err = CRYPT_OK;
+ goto done;
+error:
+ mp_clear_multi(&key->g, &key->q, &key->p, &key->x, &key->y, NULL);
+done:
+ mp_clear_multi(&tmp, &tmp2, NULL);
+ XFREE(buf);
+ return err;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/dsa/dsa_make_key.c,v $ */
+/* $Revision: 1.12 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/dsa/dsa_sign_hash.c b/crypto/userspace/libtomcrypt/pk/dsa/dsa_sign_hash.c
new file mode 100644
index 0000000..b48d5a5
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/dsa/dsa_sign_hash.c
@@ -0,0 +1,147 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include <linux/slab.h>
+
+/**
+ @file dsa_sign_hash.c
+ DSA implementation, sign a hash, Tom St Denis
+*/
+
+#ifdef LTC_MDSA
+
+/**
+ Sign a hash with DSA
+ @param in The hash to sign
+ @param inlen The length of the hash to sign
+ @param r The "r" integer of the signature (caller must initialize with mp_init() first)
+ @param s The "s" integer of the signature (caller must initialize with mp_init() first)
+ @param key A private DSA key
+ @return CRYPT_OK if successful
+*/
+int dsa_sign_hash_raw(const unsigned char *in, unsigned long inlen,
+ mp_int_t r, mp_int_t s,
+ dsa_key *key)
+{
+ mp_int k, kinv, tmp;
+ unsigned char *buf;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(r != NULL);
+ LTC_ARGCHK(s != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ if (key->type != PK_PRIVATE) {
+ return CRYPT_PK_NOT_PRIVATE;
+ }
+
+ /* check group order size */
+ if (key->qord >= LTC_MDSA_MAX_GROUP) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ buf = XMALLOC(LTC_MDSA_MAX_GROUP);
+ if (buf == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* Init our temps */
+ if ((err = mp_init_multi(&k, &kinv, &tmp, NULL)) != CRYPT_OK) { goto ERRBUF; }
+
+retry:
+
+ do {
+ /* gen random k */
+ get_random_bytes(buf, key->qord);
+
+ /* read k */
+ if ((err = mp_read_unsigned_bin(&k, buf, key->qord)) != CRYPT_OK) { goto error; }
+
+ /* k > 1 ? */
+ if (mp_cmp_d(&k, 1) != LTC_MP_GT) { goto retry; }
+
+ /* test gcd */
+ if ((err = mp_gcd(&k, &key->q, &tmp)) != CRYPT_OK) { goto error; }
+ } while (mp_cmp_d(&tmp, 1) != LTC_MP_EQ);
+
+ /* now find 1/k mod q */
+ if ((err = mp_invmod(&k, &key->q, &kinv)) != CRYPT_OK) { goto error; }
+
+ /* now find r = g^k mod p mod q */
+ if ((err = mp_exptmod(&key->g, &k, &key->p, r)) != CRYPT_OK) { goto error; }
+ if ((err = mp_mod(r, &key->q, r)) != CRYPT_OK) { goto error; }
+
+ if (mp_iszero(r) == LTC_MP_YES) { goto retry; }
+
+ /* now find s = (in + xr)/k mod q */
+ if ((err = mp_read_unsigned_bin(&tmp, (unsigned char *)in, inlen)) != CRYPT_OK) { goto error; }
+ if ((err = mp_mul(&key->x, r, s)) != CRYPT_OK) { goto error; }
+ if ((err = mp_add(s, &tmp, s)) != CRYPT_OK) { goto error; }
+ if ((err = mp_mulmod(s, &kinv, &key->q, s)) != CRYPT_OK) { goto error; }
+
+ if (mp_iszero(s) == LTC_MP_YES) { goto retry; }
+
+ err = CRYPT_OK;
+error:
+ mp_clear_multi(&k, &kinv, &tmp, NULL);
+ERRBUF:
+#ifdef LTC_CLEAN_STACK
+ zeromem(buf, LTC_MDSA_MAX_GROUP);
+#endif
+ XFREE(buf);
+ return err;
+}
+
+/**
+ Sign a hash with DSA
+ @param in The hash to sign
+ @param inlen The length of the hash to sign
+ @param out [out] Where to store the signature
+ @param outlen [in/out] The max size and resulting size of the signature
+ @param key A private DSA key
+ @return CRYPT_OK if successful
+*/
+int dsa_sign_hash(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ dsa_key *key)
+{
+ mp_int r, s;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ if (mp_init_multi(&r, &s, NULL) != CRYPT_OK) {
+ return CRYPT_MEM;
+ }
+
+ if ((err = dsa_sign_hash_raw(in, inlen, &r, &s, key)) != CRYPT_OK) {
+ goto error;
+ }
+
+ err = der_encode_sequence_multi(out, outlen,
+ LTC_ASN1_INTEGER, 1UL, &r,
+ LTC_ASN1_INTEGER, 1UL, &s,
+ LTC_ASN1_EOL, 0UL, NULL);
+
+error:
+ mp_clear_multi(&r, &s, NULL);
+ return err;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/dsa/dsa_sign_hash.c,v $ */
+/* $Revision: 1.14 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/dsa/dsa_verify_hash.c b/crypto/userspace/libtomcrypt/pk/dsa/dsa_verify_hash.c
new file mode 100644
index 0000000..3a82d1b
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/dsa/dsa_verify_hash.c
@@ -0,0 +1,126 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file dsa_verify_hash.c
+ DSA implementation, verify a signature, Tom St Denis
+*/
+
+
+#ifdef LTC_MDSA
+
+/**
+ Verify a DSA signature
+ @param r DSA "r" parameter
+ @param s DSA "s" parameter
+ @param hash The hash that was signed
+ @param hashlen The length of the hash that was signed
+ @param stat [out] The result of the signature verification, 1==valid, 0==invalid
+ @param key The corresponding public DH key
+ @return CRYPT_OK if successful (even if the signature is invalid)
+*/
+int dsa_verify_hash_raw( mp_int_t r, mp_int_t s,
+ const unsigned char *hash, unsigned long hashlen,
+ int *stat, dsa_key *key)
+{
+ mp_int w, v, u1, u2;
+ int err;
+
+ LTC_ARGCHK(r != NULL);
+ LTC_ARGCHK(s != NULL);
+ LTC_ARGCHK(stat != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* default to invalid signature */
+ *stat = 0;
+
+ /* init our variables */
+ if ((err = mp_init_multi(&w, &v, &u1, &u2, NULL)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* neither r or s can be null or >q*/
+ if (mp_iszero(r) == LTC_MP_YES || mp_iszero(s) == LTC_MP_YES || mp_cmp(r, &key->q) != LTC_MP_LT || mp_cmp(s, &key->q) != LTC_MP_LT) {
+ err = CRYPT_INVALID_PACKET;
+ goto error;
+ }
+
+ /* w = 1/s mod q */
+ if ((err = mp_invmod(s, &key->q, &w)) != CRYPT_OK) { goto error; }
+
+ /* u1 = m * w mod q */
+ if ((err = mp_read_unsigned_bin(&u1, (unsigned char *)hash, hashlen)) != CRYPT_OK) { goto error; }
+ if ((err = mp_mulmod(&u1, &w, &key->q, &u1)) != CRYPT_OK) { goto error; }
+
+ /* u2 = r*w mod q */
+ if ((err = mp_mulmod(r, &w, &key->q, &u2)) != CRYPT_OK) { goto error; }
+
+ /* v = g^u1 * y^u2 mod p mod q */
+ if ((err = mp_exptmod(&key->g, &u1, &key->p, &u1)) != CRYPT_OK) { goto error; }
+ if ((err = mp_exptmod(&key->y, &u2, &key->p, &u2)) != CRYPT_OK) { goto error; }
+ if ((err = mp_mulmod(&u1, &u2, &key->p, &v)) != CRYPT_OK) { goto error; }
+ if ((err = mp_mod(&v, &key->q, &v)) != CRYPT_OK) { goto error; }
+
+ /* if r = v then we're set */
+ if (mp_cmp(r, &v) == LTC_MP_EQ) {
+ *stat = 1;
+ }
+
+ err = CRYPT_OK;
+error:
+ mp_clear_multi(&w, &v, &u1, &u2, NULL);
+ return err;
+}
+
+/**
+ Verify a DSA signature
+ @param sig The signature
+ @param siglen The length of the signature (octets)
+ @param hash The hash that was signed
+ @param hashlen The length of the hash that was signed
+ @param stat [out] The result of the signature verification, 1==valid, 0==invalid
+ @param key The corresponding public DH key
+ @return CRYPT_OK if successful (even if the signature is invalid)
+*/
+int dsa_verify_hash(const unsigned char *sig, unsigned long siglen,
+ const unsigned char *hash, unsigned long hashlen,
+ int *stat, dsa_key *key)
+{
+ int err;
+ mp_int r, s;
+
+ if ((err = mp_init_multi(&r, &s, NULL)) != CRYPT_OK) {
+ return CRYPT_MEM;
+ }
+
+ /* decode the sequence */
+ if ((err = der_decode_sequence_multi(sig, siglen,
+ LTC_ASN1_INTEGER, 1UL, &r,
+ LTC_ASN1_INTEGER, 1UL, &s,
+ LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* do the op */
+ err = dsa_verify_hash_raw(&r, &s, hash, hashlen, stat, key);
+
+LBL_ERR:
+ mp_clear_multi(&r, &s, NULL);
+ return err;
+}
+
+#endif
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/dsa/dsa_verify_hash.c,v $ */
+/* $Revision: 1.15 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/dsa/dsa_verify_key.c b/crypto/userspace/libtomcrypt/pk/dsa/dsa_verify_key.c
new file mode 100644
index 0000000..71635d2
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/dsa/dsa_verify_key.c
@@ -0,0 +1,100 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file dsa_verify_key.c
+ DSA implementation, verify a key, Tom St Denis
+*/
+
+#ifdef LTC_MDSA
+
+/**
+ Verify a DSA key for validity
+ @param key The key to verify
+ @param stat [out] Result of test, 1==valid, 0==invalid
+ @return CRYPT_OK if successful
+*/
+int dsa_verify_key(dsa_key *key, int *stat)
+{
+ mp_int tmp, tmp2;
+ int res, err;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(stat != NULL);
+
+ /* default to an invalid key */
+ *stat = 0;
+
+ /* first make sure key->q and key->p are prime */
+ if ((err = mp_prime_is_prime(&key->q, 8, &res)) != CRYPT_OK) {
+ return err;
+ }
+ if (res == 0) {
+ return CRYPT_OK;
+ }
+
+ if ((err = mp_prime_is_prime(&key->p, 8, &res)) != CRYPT_OK) {
+ return err;
+ }
+ if (res == 0) {
+ return CRYPT_OK;
+ }
+
+ /* now make sure that g is not -1, 0 or 1 and <p */
+ if (mp_cmp_d(&key->g, 0) == LTC_MP_EQ || mp_cmp_d(&key->g, 1) == LTC_MP_EQ) {
+ return CRYPT_OK;
+ }
+ if ((err = mp_init_multi(&tmp, &tmp2, NULL)) != CRYPT_OK) { return err; }
+ if ((err = mp_sub_d(&key->p, 1, &tmp)) != CRYPT_OK) { goto error; }
+ if (mp_cmp(&tmp, &key->g) == LTC_MP_EQ || mp_cmp(&key->g, &key->p) != LTC_MP_LT) {
+ err = CRYPT_OK;
+ goto error;
+ }
+
+ /* 1 < y < p-1 */
+ if (!(mp_cmp_d(&key->y, 1) == LTC_MP_GT && mp_cmp(&key->y, &tmp) == LTC_MP_LT)) {
+ err = CRYPT_OK;
+ goto error;
+ }
+
+ /* now we have to make sure that g^q = 1, and that p-1/q gives 0 remainder */
+ if ((err = mp_div(&tmp, &key->q, &tmp, &tmp2)) != CRYPT_OK) { goto error; }
+ if (mp_iszero(&tmp2) != LTC_MP_YES) {
+ err = CRYPT_OK;
+ goto error;
+ }
+
+ if ((err = mp_exptmod(&key->g, &key->q, &key->p, &tmp)) != CRYPT_OK) { goto error; }
+ if (mp_cmp_d(&tmp, 1) != LTC_MP_EQ) {
+ err = CRYPT_OK;
+ goto error;
+ }
+
+ /* now we have to make sure that y^q = 1, this makes sure y \in g^x mod p */
+ if ((err = mp_exptmod(&key->y, &key->q, &key->p, &tmp)) != CRYPT_OK) { goto error; }
+ if (mp_cmp_d(&tmp, 1) != LTC_MP_EQ) {
+ err = CRYPT_OK;
+ goto error;
+ }
+
+ /* at this point we are out of tests ;-( */
+ err = CRYPT_OK;
+ *stat = 1;
+error:
+ mp_clear_multi(&tmp, &tmp2, NULL);
+ return err;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/dsa/dsa_verify_key.c,v $ */
+/* $Revision: 1.8 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_i2osp.c b/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_i2osp.c
new file mode 100644
index 0000000..70294a5
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_i2osp.c
@@ -0,0 +1,51 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file pkcs_1_i2osp.c
+ Integer to Octet I2OSP, Tom St Denis
+*/
+
+#ifdef LTC_PKCS_1
+
+/* always stores the same # of bytes, pads with leading zero bytes
+ as required
+ */
+
+/**
+ LTC_PKCS #1 Integer to binary
+ @param n The integer to store
+ @param modulus_len The length of the RSA modulus
+ @param out [out] The destination for the integer
+ @return CRYPT_OK if successful
+*/
+int pkcs_1_i2osp(void *n, unsigned long modulus_len, unsigned char *out)
+{
+ unsigned long size;
+
+ size = mp_unsigned_bin_size(n);
+
+ if (size > modulus_len) {
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* store it */
+ zeromem(out, modulus_len);
+ return mp_to_unsigned_bin(n, out+(modulus_len-size));
+}
+
+#endif /* LTC_PKCS_1 */
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_i2osp.c,v $ */
+/* $Revision: 1.7 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_mgf1.c b/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_mgf1.c
new file mode 100644
index 0000000..86ba218
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_mgf1.c
@@ -0,0 +1,91 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include <ncr-int.h>
+#include <linux/slab.h>
+
+/**
+ @file pkcs_1_mgf1.c
+ The Mask Generation Function (MGF1) for LTC_PKCS #1, Tom St Denis
+*/
+
+#ifdef LTC_PKCS_1
+
+/**
+ Perform LTC_PKCS #1 MGF1 (internal)
+ @param seed The seed for MGF1
+ @param seedlen The length of the seed
+ @param hash The desired hash
+ @param mask [out] The destination
+ @param masklen The length of the mask desired
+ @return CRYPT_OK if successful
+*/
+int pkcs_1_mgf1(const struct algo_properties_st *hash,
+ const unsigned char *seed, unsigned long seedlen,
+ unsigned char *mask, unsigned long masklen)
+{
+ unsigned long hLen, x;
+ ulong32 counter;
+ int err;
+ unsigned char *buf;
+
+ LTC_ARGCHK(seed != NULL);
+ LTC_ARGCHK(mask != NULL);
+
+ /* ensure valid hash */
+ if ((err = hash_is_valid(hash)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* get hash output size */
+ hLen = hash->digest_size;
+
+ /* allocate memory */
+ buf = XMALLOC(hLen);
+ if (buf == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* start counter */
+ counter = 0;
+
+ while (masklen > 0) {
+ /* handle counter */
+ STORE32H(counter, buf);
+ ++counter;
+
+ err = hash_memory_multi(hash, buf, &hLen, seed, seedlen, buf, (unsigned long) 4, NULL, 0);
+ if (err != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* store it */
+ for (x = 0; x < hLen && masklen > 0; x++, masklen--) {
+ *mask++ = buf[x];
+ }
+ }
+
+ err = CRYPT_OK;
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(buf, hLen);
+#endif
+
+ XFREE(buf);
+
+ return err;
+}
+
+#endif /* LTC_PKCS_1 */
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c,v $ */
+/* $Revision: 1.8 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_oaep_decode.c b/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_oaep_decode.c
new file mode 100644
index 0000000..717d99d
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_oaep_decode.c
@@ -0,0 +1,192 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include <ncr-int.h>
+#include <linux/slab.h>
+
+/**
+ @file pkcs_1_oaep_decode.c
+ OAEP Padding for LTC_PKCS #1, Tom St Denis
+*/
+
+#ifdef LTC_PKCS_1
+
+/**
+ LTC_PKCS #1 v2.00 OAEP decode
+ @param msg The encoded data to decode
+ @param msglen The length of the encoded data (octets)
+ @param lparam The session or system data (can be NULL)
+ @param lparamlen The length of the lparam
+ @param modulus_bitlen The bit length of the RSA modulus
+ @param hash The desired hash
+ @param out [out] Destination of decoding
+ @param outlen [in/out] The max size and resulting size of the decoding
+ @param res [out] Result of decoding, 1==valid, 0==invalid
+ @return CRYPT_OK if successful (even if invalid)
+*/
+int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen,
+ const unsigned char *lparam, unsigned long lparamlen,
+ unsigned long modulus_bitlen, const struct algo_properties_st *hash,
+ unsigned char *out, unsigned long *outlen,
+ int *res)
+{
+ unsigned char *DB, *seed, *mask;
+ unsigned long hLen, x, y, modulus_len;
+ int err;
+
+ LTC_ARGCHK(msg != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(res != NULL);
+
+ /* default to invalid packet */
+ *res = 0;
+
+ /* test valid hash */
+ if ((err = hash_is_valid(hash)) != CRYPT_OK) {
+ return err;
+ }
+
+ hLen = hash->digest_size;
+ modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);
+
+ /* test hash/message size */
+ if ((2*hLen >= (modulus_len - 2)) || (msglen != modulus_len)) {
+ return CRYPT_PK_INVALID_SIZE;
+ }
+
+ /* allocate ram for DB/mask/salt of size modulus_len */
+ DB = XMALLOC(modulus_len);
+ mask = XMALLOC(modulus_len);
+ seed = XMALLOC(hLen);
+ if (DB == NULL || mask == NULL || seed == NULL) {
+ if (DB != NULL) {
+ XFREE(DB);
+ }
+ if (mask != NULL) {
+ XFREE(mask);
+ }
+ if (seed != NULL) {
+ XFREE(seed);
+ }
+ return CRYPT_MEM;
+ }
+
+ /* ok so it's now in the form
+
+ 0x00 || maskedseed || maskedDB
+
+ 1 || hLen || modulus_len - hLen - 1
+
+ */
+
+ /* must have leading 0x00 byte */
+ if (msg[0] != 0x00) {
+ err = CRYPT_OK;
+ goto LBL_ERR;
+ }
+
+ /* now read the masked seed */
+ x = 1;
+ XMEMCPY(seed, msg + x, hLen);
+ x += hLen;
+
+ /* now read the masked DB */
+ XMEMCPY(DB, msg + x, modulus_len - hLen - 1);
+ x += modulus_len - hLen - 1;
+
+ /* compute MGF1 of maskedDB (hLen) */
+ if ((err = pkcs_1_mgf1(hash, DB, modulus_len - hLen - 1, mask, hLen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* XOR against seed */
+ for (y = 0; y < hLen; y++) {
+ seed[y] ^= mask[y];
+ }
+
+ /* compute MGF1 of seed (k - hlen - 1) */
+ if ((err = pkcs_1_mgf1(hash, seed, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* xor against DB */
+ for (y = 0; y < (modulus_len - hLen - 1); y++) {
+ DB[y] ^= mask[y];
+ }
+
+ /* now DB == lhash || PS || 0x01 || M, PS == k - mlen - 2hlen - 2 zeroes */
+
+ /* compute lhash and store it in seed [reuse temps!] */
+ x = modulus_len;
+ if (lparam != NULL) {
+ if ((err = hash_memory(hash, lparam, lparamlen, seed, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ } else {
+ /* can't pass hash_memory a NULL so use DB with zero length */
+ if ((err = hash_memory(hash, DB, 0, seed, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* compare the lhash'es */
+ if (XMEMCMP(seed, DB, hLen) != 0) {
+ err = CRYPT_OK;
+ goto LBL_ERR;
+ }
+
+ /* now zeroes before a 0x01 */
+ for (x = hLen; x < (modulus_len - hLen - 1) && DB[x] == 0x00; x++) {
+ /* step... */
+ }
+
+ /* error out if wasn't 0x01 */
+ if (x == (modulus_len - hLen - 1) || DB[x] != 0x01) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+
+ /* rest is the message (and skip 0x01) */
+ if ((modulus_len - hLen - 1 - ++x) > *outlen) {
+ *outlen = modulus_len - hLen - 1 - x;
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto LBL_ERR;
+ }
+
+ /* copy message */
+ *outlen = modulus_len - hLen - 1 - x;
+ XMEMCPY(out, DB + x, modulus_len - hLen - 1 - x);
+ x += modulus_len - hLen - 1;
+
+ /* valid packet */
+ *res = 1;
+
+ err = CRYPT_OK;
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(DB, modulus_len);
+ zeromem(seed, hLen);
+ zeromem(mask, modulus_len);
+#endif
+
+ XFREE(seed);
+ XFREE(mask);
+ XFREE(DB);
+
+ return err;
+}
+
+#endif /* LTC_PKCS_1 */
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c,v $ */
+/* $Revision: 1.13 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_oaep_encode.c b/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_oaep_encode.c
new file mode 100644
index 0000000..331516f
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_oaep_encode.c
@@ -0,0 +1,164 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include <ncr-int.h>
+#include <linux/slab.h>
+
+/**
+ @file pkcs_1_oaep_encode.c
+ OAEP Padding for LTC_PKCS #1, Tom St Denis
+*/
+
+#ifdef LTC_PKCS_1
+
+/**
+ LTC_PKCS #1 v2.00 OAEP encode
+ @param msg The data to encode
+ @param msglen The length of the data to encode (octets)
+ @param lparam A session or system parameter (can be NULL)
+ @param lparamlen The length of the lparam data
+ @param modulus_bitlen The bit length of the RSA modulus
+ @param hash The desired hash
+ @param out [out] The destination for the encoded data
+ @param outlen [in/out] The max size and resulting size of the encoded data
+ @return CRYPT_OK if successful
+*/
+int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen,
+ const unsigned char *lparam, unsigned long lparamlen,
+ unsigned long modulus_bitlen, const struct algo_properties_st *hash,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned char *DB, *seed, *mask;
+ unsigned long hLen, x, y, modulus_len;
+ int err;
+
+ LTC_ARGCHK(msg != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* test valid hash */
+ if ((err = hash_is_valid(hash)) != CRYPT_OK) {
+ return err;
+ }
+
+ hLen = hash->digest_size;
+ modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);
+
+ /* test message size */
+ if ((2*hLen >= (modulus_len - 2)) || (msglen > (modulus_len - 2*hLen - 2))) {
+ return CRYPT_PK_INVALID_SIZE;
+ }
+
+ /* allocate ram for DB/mask/salt of size modulus_len */
+ DB = XMALLOC(modulus_len);
+ mask = XMALLOC(modulus_len);
+ seed = XMALLOC(hLen);
+ if (DB == NULL || mask == NULL || seed == NULL) {
+ if (DB != NULL) {
+ XFREE(DB);
+ }
+ if (mask != NULL) {
+ XFREE(mask);
+ }
+ if (seed != NULL) {
+ XFREE(seed);
+ }
+ return CRYPT_MEM;
+ }
+
+ /* get lhash */
+ /* DB == lhash || PS || 0x01 || M, PS == k - mlen - 2hlen - 2 zeroes */
+ x = modulus_len;
+ if (lparam != NULL) {
+ if ((err = hash_memory(hash, lparam, lparamlen, DB, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ } else {
+ /* can't pass hash_memory a NULL so use DB with zero length */
+ if ((err = hash_memory(hash, DB, 0, DB, &x)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* append PS then 0x01 (to lhash) */
+ x = hLen;
+ y = modulus_len - msglen - 2*hLen - 2;
+ XMEMSET(DB+x, 0, y);
+ x += y;
+
+ /* 0x01 byte */
+ DB[x++] = 0x01;
+
+ /* message (length = msglen) */
+ XMEMCPY(DB+x, msg, msglen);
+ x += msglen;
+
+ /* now choose a random seed */
+ get_random_bytes(seed, hLen);
+
+ /* compute MGF1 of seed (k - hlen - 1) */
+ if ((err = pkcs_1_mgf1(hash, seed, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* xor against DB */
+ for (y = 0; y < (modulus_len - hLen - 1); y++) {
+ DB[y] ^= mask[y];
+ }
+
+ /* compute MGF1 of maskedDB (hLen) */
+ if ((err = pkcs_1_mgf1(hash, DB, modulus_len - hLen - 1, mask, hLen)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* XOR against seed */
+ for (y = 0; y < hLen; y++) {
+ seed[y] ^= mask[y];
+ }
+
+ /* create string of length modulus_len */
+ if (*outlen < modulus_len) {
+ *outlen = modulus_len;
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto LBL_ERR;
+ }
+
+ /* start output which is 0x00 || maskedSeed || maskedDB */
+ x = 0;
+ out[x++] = 0x00;
+ XMEMCPY(out+x, seed, hLen);
+ x += hLen;
+ XMEMCPY(out+x, DB, modulus_len - hLen - 1);
+ x += modulus_len - hLen - 1;
+
+ *outlen = x;
+
+ err = CRYPT_OK;
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(DB, modulus_len);
+ zeromem(seed, hLen);
+ zeromem(mask, modulus_len);
+#endif
+
+ XFREE(seed);
+ XFREE(mask);
+ XFREE(DB);
+
+ return err;
+}
+
+#endif /* LTC_PKCS_1 */
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_encode.c,v $ */
+/* $Revision: 1.9 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_os2ip.c b/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_os2ip.c
new file mode 100644
index 0000000..513abb6
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_os2ip.c
@@ -0,0 +1,36 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file pkcs_1_os2ip.c
+ Octet to Integer OS2IP, Tom St Denis
+*/
+#ifdef LTC_PKCS_1
+
+/**
+ Read a binary string into an mp_int
+ @param n [out] The mp_int destination
+ @param in The binary string to read
+ @param inlen The length of the binary string
+ @return CRYPT_OK if successful
+*/
+int pkcs_1_os2ip(void *n, unsigned char *in, unsigned long inlen)
+{
+ return mp_read_unsigned_bin(n, in, inlen);
+}
+
+#endif /* LTC_PKCS_1 */
+
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_os2ip.c,v $ */
+/* $Revision: 1.7 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_pss_decode.c b/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_pss_decode.c
new file mode 100644
index 0000000..5d44ce8
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_pss_decode.c
@@ -0,0 +1,168 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include <ncr-int.h>
+#include <linux/slab.h>
+
+/**
+ @file pkcs_1_pss_decode.c
+ LTC_PKCS #1 PSS Signature Padding, Tom St Denis
+*/
+
+#ifdef LTC_PKCS_1
+
+/**
+ LTC_PKCS #1 v2.00 PSS decode
+ @param msghash The hash to verify
+ @param msghashlen The length of the hash (octets)
+ @param sig The signature data (encoded data)
+ @param siglen The length of the signature data (octets)
+ @param saltlen The length of the salt used (octets)
+ @param hash_algo The desired hash
+ @param modulus_bitlen The bit length of the RSA modulus
+ @param res [out] The result of the comparison, 1==valid, 0==invalid
+ @return CRYPT_OK if successful (even if the comparison failed)
+*/
+int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen,
+ const unsigned char *sig, unsigned long siglen,
+ unsigned long saltlen, const struct algo_properties_st *hash_algo,
+ unsigned long modulus_bitlen, int *res)
+{
+ unsigned char *DB, *mask, *salt, *hash;
+ unsigned long x, y, hLen, modulus_len;
+ int err;
+
+ LTC_ARGCHK(msghash != NULL);
+ LTC_ARGCHK(res != NULL);
+
+ /* default to invalid */
+ *res = 0;
+
+ /* ensure hash is valid */
+ if ((err = hash_is_valid(hash_algo)) != CRYPT_OK) {
+ return err;
+ }
+
+ hLen = hash_algo->digest_size;
+ modulus_len = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0);
+
+ /* check sizes */
+ if ((saltlen > modulus_len) ||
+ (modulus_len < hLen + saltlen + 2) || (siglen != modulus_len)) {
+ return CRYPT_PK_INVALID_SIZE;
+ }
+
+ /* allocate ram for DB/mask/salt/hash of size modulus_len */
+ DB = XMALLOC(modulus_len);
+ mask = XMALLOC(modulus_len);
+ salt = XMALLOC(modulus_len);
+ hash = XMALLOC(modulus_len);
+ if (DB == NULL || mask == NULL || salt == NULL || hash == NULL) {
+ if (DB != NULL) {
+ XFREE(DB);
+ }
+ if (mask != NULL) {
+ XFREE(mask);
+ }
+ if (salt != NULL) {
+ XFREE(salt);
+ }
+ if (hash != NULL) {
+ XFREE(hash);
+ }
+ return CRYPT_MEM;
+ }
+
+ /* ensure the 0xBC byte */
+ if (sig[siglen-1] != 0xBC) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+
+ /* copy out the DB */
+ x = 0;
+ XMEMCPY(DB, sig + x, modulus_len - hLen - 1);
+ x += modulus_len - hLen - 1;
+
+ /* copy out the hash */
+ XMEMCPY(hash, sig + x, hLen);
+ x += hLen;
+
+ /* check the MSB */
+ if ((sig[0] & ~(0xFF >> ((modulus_len<<3) - (modulus_bitlen-1)))) != 0) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+
+ /* generate mask of length modulus_len - hLen - 1 from hash */
+ if ((err = pkcs_1_mgf1(hash_algo, hash, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* xor against DB */
+ for (y = 0; y < (modulus_len - hLen - 1); y++) {
+ DB[y] ^= mask[y];
+ }
+
+ /* now clear the first byte [make sure smaller than modulus] */
+ DB[0] &= 0xFF >> ((modulus_len<<3) - (modulus_bitlen-1));
+
+ /* DB = PS || 0x01 || salt, PS == modulus_len - saltlen - hLen - 2 zero bytes */
+
+ /* check for zeroes and 0x01 */
+ for (x = 0; x < modulus_len - saltlen - hLen - 2; x++) {
+ if (DB[x] != 0x00) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+ }
+
+ /* check for the 0x01 */
+ if (DB[x++] != 0x01) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+
+ zeromem(mask, 8);
+
+ /* M = (eight) 0x00 || msghash || salt, mask = H(M) */
+ err = hash_memory_multi(hash_algo, mask, &hLen, mask, (unsigned long)8, msghash, (unsigned long)msghashlen, DB+x, (unsigned long)saltlen, NULL, 0);
+ if (err != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* mask == hash means valid signature */
+ if (XMEMCMP(mask, hash, hLen) == 0) {
+ *res = 1;
+ }
+
+ err = CRYPT_OK;
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(DB, modulus_len);
+ zeromem(mask, modulus_len);
+ zeromem(salt, modulus_len);
+ zeromem(hash, modulus_len);
+#endif
+
+ XFREE(hash);
+ XFREE(salt);
+ XFREE(mask);
+ XFREE(DB);
+
+ return err;
+}
+
+#endif /* LTC_PKCS_1 */
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c,v $ */
+/* $Revision: 1.11 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_pss_encode.c b/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_pss_encode.c
new file mode 100644
index 0000000..9416eae
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_pss_encode.c
@@ -0,0 +1,157 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include <ncr-int.h>
+#include <linux/slab.h>
+
+/**
+ @file pkcs_1_pss_encode.c
+ LTC_PKCS #1 PSS Signature Padding, Tom St Denis
+*/
+
+#ifdef LTC_PKCS_1
+
+/**
+ LTC_PKCS #1 v2.00 Signature Encoding
+ @param msghash The hash to encode
+ @param msghashlen The length of the hash (octets)
+ @param saltlen The length of the salt desired (octets)
+ @param hash_algo The desired hash
+ @param modulus_bitlen The bit length of the RSA modulus
+ @param out [out] The destination of the encoding
+ @param outlen [in/out] The max size and resulting size of the encoded data
+ @return CRYPT_OK if successful
+*/
+int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen,
+ unsigned long saltlen, const struct algo_properties_st *hash_algo,
+ unsigned long modulus_bitlen,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned char *DB, *mask, *salt, *hash;
+ unsigned long x, y, hLen, modulus_len;
+ int err;
+
+ LTC_ARGCHK(msghash != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* ensure hash and PRNG are valid */
+ if ((err = hash_is_valid(hash_algo)) != CRYPT_OK) {
+ return err;
+ }
+
+ hLen = hash_algo->digest_size;
+ modulus_len = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0);
+
+ /* check sizes */
+ if ((saltlen > modulus_len) || (modulus_len < hLen + saltlen + 2)) {
+ return CRYPT_PK_INVALID_SIZE;
+ }
+
+ /* allocate ram for DB/mask/salt/hash of size modulus_len */
+ DB = XMALLOC(modulus_len);
+ mask = XMALLOC(modulus_len);
+ salt = XMALLOC(modulus_len);
+ hash = XMALLOC(modulus_len);
+ if (DB == NULL || mask == NULL || salt == NULL || hash == NULL) {
+ if (DB != NULL) {
+ XFREE(DB);
+ }
+ if (mask != NULL) {
+ XFREE(mask);
+ }
+ if (salt != NULL) {
+ XFREE(salt);
+ }
+ if (hash != NULL) {
+ XFREE(hash);
+ }
+ return CRYPT_MEM;
+ }
+
+
+ /* generate random salt */
+ if (saltlen > 0) {
+ get_random_bytes(salt, saltlen);
+ }
+
+ zeromem(DB, 8);
+
+ /* M = (eight) 0x00 || msghash || salt, hash = H(M) */
+ err = hash_memory_multi(hash_algo, hash, &hLen, DB, (unsigned long)8, msghash, (unsigned long)msghashlen, salt, (unsigned long)saltlen, NULL, 0);
+ if (err != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* generate DB = PS || 0x01 || salt, PS == modulus_len - saltlen - hLen - 2 zero bytes */
+ x = 0;
+ XMEMSET(DB + x, 0, modulus_len - saltlen - hLen - 2);
+ x += modulus_len - saltlen - hLen - 2;
+ DB[x++] = 0x01;
+ XMEMCPY(DB + x, salt, saltlen);
+ x += saltlen;
+
+ /* generate mask of length modulus_len - hLen - 1 from hash */
+ if ((err = pkcs_1_mgf1(hash_algo, hash, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* xor against DB */
+ for (y = 0; y < (modulus_len - hLen - 1); y++) {
+ DB[y] ^= mask[y];
+ }
+
+ /* output is DB || hash || 0xBC */
+ if (*outlen < modulus_len) {
+ *outlen = modulus_len;
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto LBL_ERR;
+ }
+
+ /* DB len = modulus_len - hLen - 1 */
+ y = 0;
+ XMEMCPY(out + y, DB, modulus_len - hLen - 1);
+ y += modulus_len - hLen - 1;
+
+ /* hash */
+ XMEMCPY(out + y, hash, hLen);
+ y += hLen;
+
+ /* 0xBC */
+ out[y] = 0xBC;
+
+ /* now clear the 8*modulus_len - modulus_bitlen most significant bits */
+ out[0] &= 0xFF >> ((modulus_len<<3) - (modulus_bitlen-1));
+
+ /* store output size */
+ *outlen = modulus_len;
+ err = CRYPT_OK;
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(DB, modulus_len);
+ zeromem(mask, modulus_len);
+ zeromem(salt, modulus_len);
+ zeromem(hash, modulus_len);
+#endif
+
+ XFREE(hash);
+ XFREE(salt);
+ XFREE(mask);
+ XFREE(DB);
+
+ return err;
+}
+
+#endif /* LTC_PKCS_1 */
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_encode.c,v $ */
+/* $Revision: 1.9 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_v1_5_decode.c b/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_v1_5_decode.c
new file mode 100644
index 0000000..1bb08e3
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_v1_5_decode.c
@@ -0,0 +1,110 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/** @file pkcs_1_v1_5_decode.c
+ *
+ * LTC_PKCS #1 v1.5 Padding. (Andreas Lange)
+ */
+
+#ifdef LTC_PKCS_1
+
+/** @brief LTC_PKCS #1 v1.5 decode.
+ *
+ * @param msg The encoded data to decode
+ * @param msglen The length of the encoded data (octets)
+ * @param block_type Block type to use in padding (\sa ltc_pkcs_1_v1_5_blocks)
+ * @param modulus_bitlen The bit length of the RSA modulus
+ * @param out [out] Destination of decoding
+ * @param outlen [in/out] The max size and resulting size of the decoding
+ * @param is_valid [out] Boolean whether the padding was valid
+ *
+ * @return CRYPT_OK if successful (even if invalid)
+ */
+int pkcs_1_v1_5_decode(const unsigned char *msg,
+ unsigned long msglen,
+ int block_type,
+ unsigned long modulus_bitlen,
+ unsigned char *out,
+ unsigned long *outlen,
+ int *is_valid)
+{
+ unsigned long modulus_len, ps_len, i;
+ int result;
+
+ /* default to invalid packet */
+ *is_valid = 0;
+
+ modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);
+
+ /* test message size */
+
+ if ((msglen > modulus_len) || (modulus_len < 11)) {
+ return CRYPT_PK_INVALID_SIZE;
+ }
+
+ /* separate encoded message */
+
+ if ((msg[0] != 0x00) || (msg[1] != (unsigned char)block_type)) {
+ result = CRYPT_INVALID_PACKET;
+ goto bail;
+ }
+
+ if (block_type == LTC_LTC_PKCS_1_EME) {
+ for (i = 2; i < modulus_len; i++) {
+ /* separator */
+ if (msg[i] == 0x00) { break; }
+ }
+ ps_len = i++ - 2;
+
+ if ((i >= modulus_len) || (ps_len < 8)) {
+ /* There was no octet with hexadecimal value 0x00 to separate ps from m,
+ * or the length of ps is less than 8 octets.
+ */
+ result = CRYPT_INVALID_PACKET;
+ goto bail;
+ }
+ } else {
+ for (i = 2; i < modulus_len - 1; i++) {
+ if (msg[i] != 0xFF) { break; }
+ }
+
+ /* separator check */
+ if (msg[i] != 0) {
+ /* There was no octet with hexadecimal value 0x00 to separate ps from m. */
+ result = CRYPT_INVALID_PACKET;
+ goto bail;
+ }
+
+ ps_len = i - 2;
+ }
+
+ if (*outlen < (msglen - (2 + ps_len + 1))) {
+ *outlen = msglen - (2 + ps_len + 1);
+ result = CRYPT_BUFFER_OVERFLOW;
+ goto bail;
+ }
+
+ *outlen = (msglen - (2 + ps_len + 1));
+ XMEMCPY(out, &msg[2 + ps_len + 1], *outlen);
+
+ /* valid packet */
+ *is_valid = 1;
+ result = CRYPT_OK;
+bail:
+ return result;
+} /* pkcs_1_v1_5_decode */
+
+#endif /* #ifdef LTC_PKCS_1 */
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_decode.c,v $ */
+/* $Revision: 1.7 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_v1_5_encode.c b/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_v1_5_encode.c
new file mode 100644
index 0000000..048fe69
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_v1_5_encode.c
@@ -0,0 +1,95 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/*! \file pkcs_1_v1_5_encode.c
+ *
+ * LTC_PKCS #1 v1.5 Padding (Andreas Lange)
+ */
+
+#ifdef LTC_PKCS_1
+
+/*! \brief LTC_PKCS #1 v1.5 encode.
+ *
+ * \param msg The data to encode
+ * \param msglen The length of the data to encode (octets)
+ * \param block_type Block type to use in padding (\sa ltc_pkcs_1_v1_5_blocks)
+ * \param modulus_bitlen The bit length of the RSA modulus
+ * \param out [out] The destination for the encoded data
+ * \param outlen [in/out] The max size and resulting size of the encoded data
+ *
+ * \return CRYPT_OK if successful
+ */
+int pkcs_1_v1_5_encode(const unsigned char *msg,
+ unsigned long msglen,
+ int block_type,
+ unsigned long modulus_bitlen,
+ unsigned char *out,
+ unsigned long *outlen)
+{
+ unsigned long modulus_len, ps_len, i;
+ unsigned char *ps;
+ int result;
+
+ /* valid block_type? */
+ if ((block_type != LTC_LTC_PKCS_1_EMSA) &&
+ (block_type != LTC_LTC_PKCS_1_EME)) {
+ return CRYPT_PK_INVALID_PADDING;
+ }
+
+ modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);
+
+ /* test message size */
+ if ((msglen + 11) > modulus_len) {
+ return CRYPT_PK_INVALID_SIZE;
+ }
+
+ if (*outlen < modulus_len) {
+ *outlen = modulus_len;
+ result = CRYPT_BUFFER_OVERFLOW;
+ goto bail;
+ }
+
+ /* generate an octets string PS */
+ ps = &out[2];
+ ps_len = modulus_len - msglen - 3;
+
+ if (block_type == LTC_LTC_PKCS_1_EME) {
+ /* now choose a random ps */
+ get_random_bytes(ps, ps_len);
+
+ /* transform zero bytes (if any) to non-zero random bytes */
+ for (i = 0; i < ps_len; i++) {
+ while (ps[i] == 0) {
+ get_random_bytes(&ps[i], 1);
+ }
+ }
+ } else {
+ XMEMSET(ps, 0xFF, ps_len);
+ }
+
+ /* create string of length modulus_len */
+ out[0] = 0x00;
+ out[1] = (unsigned char)block_type; /* block_type 1 or 2 */
+ out[2 + ps_len] = 0x00;
+ XMEMCPY(&out[2 + ps_len + 1], msg, msglen);
+ *outlen = modulus_len;
+
+ result = CRYPT_OK;
+bail:
+ return result;
+} /* pkcs_1_v1_5_encode */
+
+#endif /* #ifdef LTC_PKCS_1 */
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_encode.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/rsa/rsa_decrypt_key.c b/crypto/userspace/libtomcrypt/pk/rsa/rsa_decrypt_key.c
new file mode 100644
index 0000000..ba16e32
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/rsa/rsa_decrypt_key.c
@@ -0,0 +1,107 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include "ncr-int.h"
+#include <linux/slab.h>
+
+/**
+ @file rsa_decrypt_key.c
+ RSA LTC_PKCS #1 Decryption, Tom St Denis and Andreas Lange
+*/
+
+#ifdef LTC_MRSA
+
+/**
+ LTC_PKCS #1 decrypt then v1.5 or OAEP depad
+ @param in The ciphertext
+ @param inlen The length of the ciphertext (octets)
+ @param out [out] The plaintext
+ @param outlen [in/out] The max size and resulting size of the plaintext (octets)
+ @param lparam The system "lparam" value
+ @param lparamlen The length of the lparam value (octets)
+ @param hash The desired hash
+ @param padding Type of padding (LTC_LTC_PKCS_1_OAEP or LTC_LTC_PKCS_1_V1_5)
+ @param stat [out] Result of the decryption, 1==valid, 0==invalid
+ @param key The corresponding private RSA key
+ @return CRYPT_OK if succcessul (even if invalid)
+*/
+int rsa_decrypt_key_ex(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ const unsigned char *lparam, unsigned long lparamlen,
+ const struct algo_properties_st *hash, int padding,
+ int *stat, rsa_key *key)
+{
+ unsigned long modulus_bitlen, modulus_bytelen, x;
+ int err;
+ unsigned char *tmp;
+
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(stat != NULL);
+
+ /* default to invalid */
+ *stat = 0;
+
+ /* valid padding? */
+
+ if ((padding != LTC_LTC_PKCS_1_V1_5) &&
+ (padding != LTC_LTC_PKCS_1_OAEP)) {
+ return CRYPT_PK_INVALID_PADDING;
+ }
+
+ if (padding == LTC_LTC_PKCS_1_OAEP) {
+ /* valid hash ? */
+ if ((err = hash_is_valid(hash)) != CRYPT_OK) {
+ return err;
+ }
+ }
+
+ /* get modulus len in bits */
+ modulus_bitlen = mp_count_bits( (&key->N));
+
+ /* outlen must be at least the size of the modulus */
+ modulus_bytelen = mp_unsigned_bin_size( (&key->N));
+ if (modulus_bytelen != inlen) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* allocate ram */
+ tmp = XMALLOC(inlen);
+ if (tmp == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* rsa decode the packet */
+ x = inlen;
+ if ((err = rsa_exptmod(in, inlen, tmp, &x, PK_PRIVATE, key)) != CRYPT_OK) {
+ XFREE(tmp);
+ return err;
+ }
+
+ if (padding == LTC_LTC_PKCS_1_OAEP) {
+ /* now OAEP decode the packet */
+ err = pkcs_1_oaep_decode(tmp, x, lparam, lparamlen, modulus_bitlen, hash,
+ out, outlen, stat);
+ } else {
+ /* now LTC_PKCS #1 v1.5 depad the packet */
+ err = pkcs_1_v1_5_decode(tmp, x, LTC_LTC_PKCS_1_EME, modulus_bitlen, out, outlen, stat);
+ }
+
+ XFREE(tmp);
+ return err;
+}
+
+#endif /* LTC_MRSA */
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_decrypt_key.c,v $ */
+/* $Revision: 1.10 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/rsa/rsa_encrypt_key.c b/crypto/userspace/libtomcrypt/pk/rsa/rsa_encrypt_key.c
new file mode 100644
index 0000000..8d3f2db
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/rsa/rsa_encrypt_key.c
@@ -0,0 +1,96 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include "ncr-int.h"
+
+/**
+ @file rsa_encrypt_key.c
+ RSA LTC_PKCS #1 encryption, Tom St Denis and Andreas Lange
+*/
+
+#ifdef LTC_MRSA
+
+/**
+ (LTC_PKCS #1 v2.0) OAEP pad then encrypt
+ @param in The plaintext
+ @param inlen The length of the plaintext (octets)
+ @param out [out] The ciphertext
+ @param outlen [in/out] The max size and resulting size of the ciphertext
+ @param lparam The system "lparam" for the encryption
+ @param lparamlen The length of lparam (octets)
+ @param hash The desired hash
+ @param padding Type of padding (LTC_LTC_PKCS_1_OAEP or LTC_LTC_PKCS_1_V1_5)
+ @param key The RSA key to encrypt to
+ @return CRYPT_OK if successful
+*/
+int rsa_encrypt_key_ex(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ const unsigned char *lparam, unsigned long lparamlen,
+ const struct algo_properties_st *hash, int padding, rsa_key *key)
+{
+ unsigned long modulus_bitlen, modulus_bytelen, x;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* valid padding? */
+ if ((padding != LTC_LTC_PKCS_1_V1_5) &&
+ (padding != LTC_LTC_PKCS_1_OAEP)) {
+ return CRYPT_PK_INVALID_PADDING;
+ }
+
+ if (padding == LTC_LTC_PKCS_1_OAEP) {
+ /* valid hash? */
+ if ((err = hash_is_valid(hash)) != CRYPT_OK) {
+ return err;
+ }
+ }
+
+ /* get modulus len in bits */
+ modulus_bitlen = mp_count_bits( (&key->N));
+
+ /* outlen must be at least the size of the modulus */
+ modulus_bytelen = mp_unsigned_bin_size( (&key->N));
+ if (modulus_bytelen > *outlen) {
+ *outlen = modulus_bytelen;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ if (padding == LTC_LTC_PKCS_1_OAEP) {
+ /* OAEP pad the key */
+ x = *outlen;
+ if ((err = pkcs_1_oaep_encode(in, inlen, lparam,
+ lparamlen, modulus_bitlen, hash,
+ out, &x)) != CRYPT_OK) {
+ return err;
+ }
+ } else {
+ /* LTC_PKCS #1 v1.5 pad the key */
+ x = *outlen;
+ if ((err = pkcs_1_v1_5_encode(in, inlen, LTC_LTC_PKCS_1_EME,
+ modulus_bitlen,
+ out, &x)) != CRYPT_OK) {
+ return err;
+ }
+ }
+
+ /* rsa exptmod the OAEP or LTC_PKCS #1 v1.5 pad */
+ return rsa_exptmod(out, x, out, outlen, PK_PUBLIC, key);
+}
+
+#endif /* LTC_MRSA */
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_encrypt_key.c,v $ */
+/* $Revision: 1.10 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/rsa/rsa_export.c b/crypto/userspace/libtomcrypt/pk/rsa/rsa_export.c
new file mode 100644
index 0000000..c5e8ff0
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/rsa/rsa_export.c
@@ -0,0 +1,87 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include <ncr-int.h>
+#include <linux/slab.h>
+/**
+ @file rsa_export.c
+ Export RSA LTC_PKCS keys, Tom St Denis
+*/
+
+#ifdef LTC_MRSA
+
+/**
+ This will export either an RSAPublicKey or RSAPrivateKey [defined in LTC_PKCS #1 v2.1]
+ @param out [out] Destination of the packet
+ @param outlen [in/out] The max size and resulting size of the packet
+ @param type The type of exported key (PK_PRIVATE or PK_PUBLIC)
+ @param key The RSA key to export
+ @return CRYPT_OK if successful
+*/
+int rsa_export(unsigned char *out, unsigned long *outlen, int type, rsa_key *key)
+{
+ unsigned long zero=0;
+ int err;
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* type valid? */
+ if (!(key->type == PK_PRIVATE) && (type == PK_PRIVATE)) {
+ return CRYPT_PK_INVALID_TYPE;
+ }
+
+ if (type == PK_PRIVATE) {
+ /* private key */
+ /* output is
+ Version, n, e, d, p, q, d mod (p-1), d mod (q - 1), 1/q mod p
+ */
+ return der_encode_sequence_multi(out, outlen,
+ LTC_ASN1_SHORT_INTEGER, 1UL, &zero,
+ LTC_ASN1_INTEGER, 1UL, &key->N,
+ LTC_ASN1_INTEGER, 1UL, &key->e,
+ LTC_ASN1_INTEGER, 1UL, &key->d,
+ LTC_ASN1_INTEGER, 1UL, &key->p,
+ LTC_ASN1_INTEGER, 1UL, &key->q,
+ LTC_ASN1_INTEGER, 1UL, &key->dP,
+ LTC_ASN1_INTEGER, 1UL, &key->dQ,
+ LTC_ASN1_INTEGER, 1UL, &key->qP,
+ LTC_ASN1_EOL, 0UL, NULL);
+ } else {
+ unsigned long tmplen = (mp_count_bits(&key->N)/8)*2+8;
+ unsigned char* tmp = XMALLOC(tmplen);
+
+ if (tmp == NULL) {
+ return CRYPT_MEM;
+ }
+
+ err = der_encode_sequence_multi(tmp, &tmplen,
+ LTC_ASN1_INTEGER, 1UL, &key->N,
+ LTC_ASN1_INTEGER, 1UL, &key->e,
+ LTC_ASN1_EOL, 0UL, NULL);
+ if (err != CRYPT_OK) {
+ goto error;
+ }
+
+ err = der_encode_subject_public_key_info(out, outlen,
+ PKA_RSA, tmp, tmplen, LTC_ASN1_NULL, NULL, 0);
+
+error:
+ XFREE(tmp);
+ return err;
+ }
+}
+
+#endif /* LTC_MRSA */
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_export.c,v $ */
+/* $Revision: 1.17 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/rsa/rsa_exptmod.c b/crypto/userspace/libtomcrypt/pk/rsa/rsa_exptmod.c
new file mode 100644
index 0000000..35ebfe3
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/rsa/rsa_exptmod.c
@@ -0,0 +1,147 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ *
+ * Added RSA blinding --nmav
+ */
+#include "tomcrypt.h"
+
+/**
+ @file rsa_exptmod.c
+ RSA LTC_PKCS exptmod, Tom St Denis
+*/
+
+#ifdef LTC_MRSA
+
+/**
+ Compute an RSA modular exponentiation
+ @param in The input data to send into RSA
+ @param inlen The length of the input (octets)
+ @param out [out] The destination
+ @param outlen [in/out] The max size and resulting size of the output
+ @param which Which exponent to use, e.g. PK_PRIVATE or PK_PUBLIC
+ @param key The RSA key to use
+ @return CRYPT_OK if successful
+*/
+int rsa_exptmod(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen, int which,
+ rsa_key *key)
+{
+ mp_int tmp, tmpa, tmpb, rnd, rndi /* inverse of rnd */;
+ unsigned long x;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* is the key of the right type for the operation? */
+ if (which == PK_PRIVATE && (key->type != PK_PRIVATE)) {
+ return CRYPT_PK_NOT_PRIVATE;
+ }
+
+ /* must be a private or public operation */
+ if (which != PK_PRIVATE && which != PK_PUBLIC) {
+ return CRYPT_PK_INVALID_TYPE;
+ }
+
+ /* init and copy into tmp */
+ if ((err = mp_init_multi(&tmp, &tmpa, &tmpb, &rnd, &rndi, NULL)) != CRYPT_OK)
+ { return err; }
+ if ((err = mp_read_unsigned_bin(&tmp, (unsigned char *)in, (int)inlen)) != CRYPT_OK)
+ { goto error; }
+
+ /* sanity check on the input */
+ if (mp_cmp(&key->N, &tmp) == LTC_MP_LT) {
+ err = CRYPT_PK_INVALID_SIZE;
+ goto error;
+ }
+
+ /* are we using the private exponent and is the key optimized? */
+ if (which == PK_PRIVATE) {
+ /* do blinding */
+ err = mp_rand(&rnd, mp_count_bits(&key->N));
+ if (err != CRYPT_OK) {
+ goto error;
+ }
+
+ /* rndi = 1/rnd mod N */
+ err = mp_invmod( &rnd, &key->N, &rndi);
+ if (err != CRYPT_OK) {
+ goto error;
+ }
+
+ /* rnd = rnd^e */
+ err = mp_exptmod( &rnd, &key->e, &key->N, &rnd);
+ if (err != CRYPT_OK) {
+ goto error;
+ }
+
+ /* tmp = tmp*rnd mod N */
+ err = mp_mulmod( &tmp, &rnd, &key->N, &tmp);
+ if (err != CRYPT_OK) {
+ goto error;
+ }
+
+ /* tmpa = tmp^dP mod p */
+ if ((err = mp_exptmod(&tmp, &key->dP, &key->p, &tmpa)) != CRYPT_OK) { goto error; }
+
+ /* tmpb = tmp^dQ mod q */
+ if ((err = mp_exptmod(&tmp, &key->dQ, &key->q, &tmpb)) != CRYPT_OK) { goto error; }
+
+ /* tmp = (tmpa - tmpb) * qInv (mod p) */
+ if ((err = mp_sub(&tmpa, &tmpb, &tmp)) != CRYPT_OK) { goto error; }
+ if ((err = mp_mulmod(&tmp, &key->qP, &key->p, &tmp)) != CRYPT_OK) { goto error; }
+
+ /* tmp = tmpb + q * tmp */
+ if ((err = mp_mul(&tmp, &key->q, &tmp)) != CRYPT_OK) { goto error; }
+ if ((err = mp_add(&tmp, &tmpb, &tmp)) != CRYPT_OK) { goto error; }
+
+ /* unblind */
+ err = mp_mulmod( &tmp, &rndi, &key->N, &tmp);
+ if (err != CRYPT_OK) {
+ goto error;
+ }
+ } else {
+ /* exptmod it */
+ if ((err = mp_exptmod(&tmp, &key->e, &key->N, &tmp)) != CRYPT_OK) { goto error; }
+ }
+
+ /* read it back */
+ x = (unsigned long)mp_unsigned_bin_size(&key->N);
+ if (x > *outlen) {
+ *outlen = x;
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto error;
+ }
+
+ /* this should never happen ... */
+ if (mp_unsigned_bin_size(&tmp) > mp_unsigned_bin_size(&key->N)) {
+ err = CRYPT_ERROR;
+ goto error;
+ }
+ *outlen = x;
+
+ /* convert it */
+ zeromem(out, x);
+ if ((err = mp_to_unsigned_bin(&tmp, out+(x-mp_unsigned_bin_size(&tmp)))) != CRYPT_OK) { goto error; }
+
+ /* clean up and return */
+ err = CRYPT_OK;
+error:
+ mp_clear_multi(&tmp, &tmpa, &tmpb, &rnd, &rndi, NULL);
+ return err;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_exptmod.c,v $ */
+/* $Revision: 1.18 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/rsa/rsa_free.c b/crypto/userspace/libtomcrypt/pk/rsa/rsa_free.c
new file mode 100644
index 0000000..d38b266
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/rsa/rsa_free.c
@@ -0,0 +1,34 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+
+/**
+ @file rsa_free.c
+ Free an RSA key, Tom St Denis
+*/
+
+#ifdef LTC_MRSA
+
+/**
+ Free an RSA key from memory
+ @param key The RSA key to free
+*/
+void rsa_free(rsa_key *key)
+{
+ LTC_ARGCHKVD(key != NULL);
+ mp_clear_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, &key->p, &key->q, NULL);
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_free.c,v $ */
+/* $Revision: 1.10 $ */
+/* $Date: 2007/05/12 14:32:35 $ */
diff --git a/crypto/userspace/libtomcrypt/pk/rsa/rsa_import.c b/crypto/userspace/libtomcrypt/pk/rsa/rsa_import.c
new file mode 100644
index 0000000..8bd8c47
--- /dev/null
+++ b/crypto/userspace/libtomcrypt/pk/rsa/rsa_import.c
@@ -0,0 +1,128 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, [email protected], http://libtom.org
+ */
+#include "tomcrypt.h"
+#include <linux/slab.h>
+
+/**
+ @file rsa_import.c
+ Import a LTC_PKCS RSA key, Tom St Denis
+*/
+
+#ifdef LTC_MRSA
+
+/**
+ Import an RSAPublicKey or RSAPrivateKey [two-prime only, only support >= 1024-bit keys, defined in LTC_PKCS #1 v2.1]
+ @param in The packet to import from
+ @param inlen It's length (octets)
+ @param key [out] Destination for newly imported key
+ @return CRYPT_OK if successful, upon error allocated memory is freed
+*/
+int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key)
+{
+ int err;
+ mp_int zero;
+ unsigned char *tmpbuf=NULL;
+ unsigned long tmpbuf_len;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* init key */
+ if ((err = mp_init_multi(&key->e, &key->d, &key->N, &key->dQ,
+ &key->dP, &key->qP, &key->p, &key->q, NULL)) != CRYPT_OK