crypt_sha.c revision 1dbc1fed8be6e82e676ff3f124628dc470058bfb
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (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
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Portions of this code from crypt_bsdmd5.so (bsdmd5.c) :
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <phk@login.dknet.dk> wrote this file. As long as you retain this notice you
* can do whatever you want with this stuff. If we meet some day, and you think
* this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
* ----------------------------------------------------------------------------
*
* $FreeBSD: crypt.c,v 1.5 1996/10/14 08:34:02 phk Exp $
*
*/
/*
* Implements the specification from:
*
*
* Portions of the code taken from inspired by or verified against the
* source in the above document which is licensed as:
*
* "Released into the Public Domain by Ulrich Drepper <drepper@redhat.com>."
*/
#include <sys/sysmacros.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <alloca.h>
#include <sha2.h>
#include <crypt.h>
#define MAX_SALT_LEN 16
#define ROUNDS_DEFAULT 5000
#define ROUNDS_MIN 1000
#define ROUNDS_MAX 999999999
#ifdef CRYPT_SHA256
#define DIGEST_CTX SHA256_CTX
#define DIGESTInit SHA256Init
#define DIGESTUpdate SHA256Update
#define DIGESTFinal SHA256Final
#define DIGEST_LEN SHA256_DIGEST_LENGTH
#define MIXCHARS 32
static const char crypt_alg_magic[] = "$5";
#define DIGEST_CTX SHA512_CTX
#define DIGESTInit SHA512Init
#define DIGESTUpdate SHA512Update
#define DIGESTFinal SHA512Final
#define DIGEST_LEN SHA512_DIGEST_LENGTH
#define MIXCHARS 64
static const char crypt_alg_magic[] = "$6";
#else
#error "One of CRYPT_256 or CRYPT_512 must be defined"
#endif
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
{ \
int n = (N); \
while (--n >= 0 && ctbufflen > 0) { \
*p++ = b64t[w & 0x3f]; \
w >>= 6; \
ctbufflen--; \
} \
}
static void
{
while (--n >= 0) {
*s++ = b64t[v & 0x3f];
v >>= 6;
}
}
#define ROUNDS "rounds="
/*
* get the integer value after rounds= where ever it occurs in the string.
* if the last char after the int is a , or $ that is fine anything else is an
* error.
*/
static uint32_t
getrounds(const char *s)
{
char *r, *p, *e;
long val;
if (s == NULL)
return (0);
return (0);
}
return (0);
}
p = r + ROUNDSLEN;
errno = 0;
/*
* An error occurred or there is non-numeric stuff at the end
* which isn't one of the crypt(3c) special chars ',' or '$'
*/
!(*e == '\0' || *e == ',' || *e == '$')) {
return (0);
}
}
/* ARGSUSED4 */
char *
crypt_genhash_impl(char *ctbuffer,
const char *plaintext,
const char *switchsalt,
const char **params)
{
int salt_len, plaintext_len, i;
char *salt;
uchar_t A[DIGEST_LEN];
uchar_t B[DIGEST_LEN];
int rounds = ROUNDS_DEFAULT;
int srounds = 0;
char *p;
char *P, *Pp;
char *S, *Sp;
/* Refine the salt */
salt = (char *)switchsalt;
/* skip our magic string */
}
if (srounds != 0) {
if (p != NULL)
salt = p + 1;
}
/* 1. */
DIGESTInit(&ctxA);
/* 2. The password first, since that is what is most unknown */
/* 3. Then the raw salt */
/* 4. - 8. */
DIGESTInit(&ctxB);
DIGESTFinal(B, &ctxB);
/* 9. - 10. */
DIGESTUpdate(&ctxA, B, i);
/* 11. */
for (i = plaintext_len; i > 0; i >>= 1) {
if ((i & 1) != 0) {
} else {
}
}
/* 12. */
DIGESTFinal(A, &ctxA);
/* 13. - 15. */
DIGESTInit(&ctxDP);
for (i = 0; i < plaintext_len; i++)
/* 16. */
}
/* 17. - 19. */
DIGESTInit(&ctxDS);
for (i = 0; i < 16 + (uint8_t)A[0]; i++)
/* 20. */
}
/* 21. */
for (i = 0; i < rounds; i++) {
DIGESTInit(&ctxC);
if ((i & 1) != 0) {
} else {
if (i == 0)
else
}
if (i % 3 != 0) {
}
if (i % 7 != 0) {
}
if ((i & 1) != 0) {
if (i == 0)
else
} else {
}
}
/* 22. Now make the output string */
if (custom_rounds) {
} else {
"%s$", crypt_alg_magic);
}
#ifdef CRYPT_SHA256
#endif
*p = '\0';
(void) memset(A, 0, sizeof (A));
(void) memset(B, 0, sizeof (B));
return (ctbuffer);
}
/* ARGSUSED3 */
char *
crypt_gensalt_impl(char *gsbuffer,
const char *oldsalt,
const char **params)
{
int fd;
int err;
uint32_t confrounds = 0;
int i;
} else {
return (NULL);
}
}
/*
* If the config file has a higher value for rounds= than what
* was in the old salt use that, otherwise keep what was in the
* old salt.
*/
if (confrounds > saltrounds) {
}
return (NULL);
}
return (NULL);
}
if (saltrounds > 0) {
"%s$rounds=%d$",
goto fail;
} else {
goto fail;
}
goto fail;
goto fail;
return (gsbuffer);
fail:
return (gsbuffer);
}