/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* crypto.c
*
* Copyright (c) 1997, by Sun Microsystems, Inc.
* All rights reserved.
*
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include "dh_gssapi.h"
#include "crypto.h"
/* Release the storage for a signature */
void
{
sig->dh_signature_len = 0;
}
/* Release the storage for a gss_buffer */
void
{
b->length = 0;
}
typedef struct cipher_entry {
typedef struct verifer_entry {
typedef struct QOP_entry {
} QOP_entry;
/*
* Return the length produced by using cipher entry c given the supplied len
*/
static unsigned int
{
unsigned int pad;
}
/* EXPORT DELETE START */
/*
* an CBC initialization vector ivec.
* If the mode is encrypt we will use the following pattern if the number
* of keys is odd
* encrypt(buf, k[0]), decrypt(buf, k[1]), encrypt(buf, k[2])
* decrypt(buf, k[4]) ... encrypt(buf, k[keynum - 1])
* If we have an even number of keys and additional encryption will be
* done with the first key, i.e., ecrypt(buf, k[0]);
* vector. The new initialization vector will be the vector return from the
* last encryption.
*
* In the decryption case we reverse the proccess. Note in this case
* the return ivec will be from the first decryption.
*/
static int
{
/* Get the direction of ciphering */
/* Get the remaining flags from mode */
int i, j, stat;
/* Do we have at least one key */
if (keynum < 1)
return (DESERR_BADPARAM);
/* Save the passed in ivec */
/* For each key do the appropriate cipher */
for (i = 0; i < keynum; i++) {
if (mode & DES_DECRYPT && i == 0)
if (DES_FAILED(stat))
return (stat);
}
/*
* If we have an even number of keys then do an extra round of
*/
if (keynum % 2 == 0)
/* If were decrypting ivec is set from first decryption */
if (mode & DES_DECRYPT)
return (stat);
}
/* EXPORT DELETE END */
/*
* DesN crypt packaged for use as a cipher entry
*/
static OM_uint32
{
/* EXPORT DELETE START */
return (DH_BADARG_FAILURE);
/*
* We all ways start of with ivec set to zeros. There is no
* good way to maintain ivecs since packets could be out of sequence
* duplicated or worst of all lost. Under these conditions the
* higher level protocol would have to some how resync the ivecs
* on both sides and start again. Theres no mechanism for this in
* GSS.
*/
/* Do the encryption/decryption */
/* EXPORT DELETE END */
if (DES_FAILED(stat))
return (DH_CIPHER_FAILURE);
return (DH_SUCCESS);
}
/*
* Package up plain des cbc crypt for use as a cipher entry.
*/
static OM_uint32
{
/* EXPORT DELETE START */
return (DH_BADARG_FAILURE);
/* Set the ivec to zeros and then cbc crypt the result */
/* EXPORT DELETE END */
if (DES_FAILED(stat))
return (DH_CIPHER_FAILURE);
return (DH_SUCCESS);
}
/*
* MD5_verifier: This is a verifier routine suitable for use in a
* verifier entry. It calculates the MD5 check sum over an optional
* msg and a token. It signs it using the supplied cipher_proc and stores
* the result in signature.
*
* Note signature should already be allocated and be large enough to
* hold the signature after its been encrypted. If keys is null, then
* we will just return the unencrypted check sum.
*/
static OM_uint32
{
/* Initialize the MD5 context */
/* If we have a message to digest, digest it */
if (msg)
/* Digest the supplied token */
/* Finalize the sum. The MD5 context contains the digets */
/* Copy the digest to the signature */
/* If we have keys encrypt it */
return (DH_SUCCESS);
}
/* Cipher table */
static
{ NULL, 1},
{ __dh_desN_crypt, 8},
{ __dh_des_crypt, 8}
};
/* Verifier table */
static
};
/* QOP table */
static
{ 0, &verifier_tab[0] },
{ 0, &verifier_tab[1] }
};
/*
* __dh_is_valid_QOP: Return true if qop is valid entry into the QOP
* table, else return false.
*/
{
return (is_valid);
}
/*
* __alloc_sig: Allocate a signature for a given QOP. This takes into
* account the size of the signature after padding for the encryption
* routine.
*/
{
verifier_entry *v;
/* Check that the QOP is valid */
if (!__dh_is_valid_QOP(qop))
return (DH_UNKNOWN_QOP);
/* Get the verifier entry from the QOP entry */
/* Calulate the length needed for the signature */
/* Allocate the signature */
sig->dh_signature_len = 0;
return (DH_NOMEM_FAILURE);
}
stat = DH_SUCCESS;
return (stat);
}
/*
* __get_sig_size: Return the total size needed for a signature given a QOP.
*/
{
/* Check for valid QOP */
if (__dh_is_valid_QOP(qop)) {
/* Get the verifier entry */
/* Return the size include the padding needed for encryption */
return (DH_SUCCESS);
}
*size = 0;
return (DH_UNKNOWN_QOP);
}
/*
* __mk_sig: Generate a signature using a given qop over a token of a
* given length and an optional message. We use the supplied keys to
* encrypt the check sum if they are available. The output is place
* in a preallocate signature, that was allocated using __alloc_sig.
*/
char *tok, /* The token to sign */
long len, /* The tokens length */
{
verifier_entry *v; /* Verifier entry */
/* Make sure the QOP is valid */
if (!__dh_is_valid_QOP(qop))
return (DH_UNKNOWN_QOP);
/* Grab the verifier entry for the qop */
/* Package the token for use in a verifier_proc */
/*
* Calculate the signature using the supplied keys. If keys
* is null, the the v->signer->cipher routine will not be called
* and sig will not be encrypted.
*/
return (stat);
}
/*
* __verify_sig: Verify that the supplied signature, sig, is the same
* as the token verifier
*/
{
/* Check the QOP */
if (!__dh_is_valid_QOP(qop))
return (DH_UNKNOWN_QOP);
/* Package up the supplied signature */
/* Get the cipher proc to use from the verifier entry for qop */
/* Encrypt the check sum using the supplied set of keys */
return (stat);
/* Compare the signatures */
return (DH_SUCCESS);
return (stat);
}
/*
* __cmpsig: Return true if two signatures are the same, else false.
*/
{
}
/*
* wrap_msg_body: Wrap the message pointed to be in into a
* message pointed to by out that has ben padded out by pad bytes.
*
* The output message looks like:
* out->length = total length of out->value including any padding
* out->value points to memory as follows:
* +------------+-------------------------+---------|
* | in->length | in->value | XDR PAD |
* +------------+-------------------------+---------|
* 4 bytes in->length bytes 0 - 3
*/
static OM_uint32
{
/* Make sure the address of len points to a 32 bit word */
return (DH_ENCODE_FAILURE);
return (DH_ENCODE_FAILURE);
/* Allocate the output buffer and set the length */
return (DH_NOMEM_FAILURE);
/* Create xdr stream to wrap into */
/* Wrap the bytes in value */
return (DH_ENCODE_FAILURE);
}
return (DH_SUCCESS);
}
/*
* __QOPSeal: Wrap the input message placing the output in output given
* a valid QOP. If confidentialiy is requested it is ignored. We can't
* support privacy. The return flag will always be zero.
*/
int conf_req, /* Do we want privacy ? */
int *conf_ret /* Did we encrypt it? */)
{
/* Check for valid QOP */
if (!__dh_is_valid_QOP(qop))
return (DH_UNKNOWN_QOP);
/* Wrap the message */
!= DH_SUCCESS)
return (stat);
return (stat);
}
/*
* unwrap_msg_body: Unwrap the message, that was wrapped from above
*/
static OM_uint32
{
/* Create an xdr stream to on wrap in */
/* Unwrap the input into out->value */
return (DH_DECODE_FAILURE);
/* set the length */
return (DH_SUCCESS);
}
/*
* __QOPUnSeal: Unwrap the input message into output using the supplied QOP.
* Note it is the callers responsibility to release the allocated output
* buffer. If conf_req is true we return DH_CIPHER_FAILURE since we don't
* support privacy.
*/
int conf_req, /* Is the message encrypted */
{
/* Check that the qop is valid */
if (!__dh_is_valid_QOP(qop))
return (DH_UNKNOWN_QOP);
/* Set output to sane values */
/* Fail if this is privacy */
if (conf_req)
return (DH_CIPHER_FAILURE);
/* Unwrap the input into the output, return the status */
return (stat);
}