1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
|
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include "xcrypt-private.h"
#include "xcrypt.h"
#define SHA_DIGESTSIZE 20
/* Define our magic string to mark salt for SHA1 "encryption"
replacement. */
const char *sha_salt_prefix = "{SHA}";
/* Table with characters for base64 transformation. */
static const char *b64 =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static int
base64encode (char *encoded, const unsigned char *string, int len)
{
int i;
char *p;
p = encoded;
for (i = 0; i < len - 2; i += 3)
{
*p++ = b64[(string[i] >> 2) & 0x3F];
*p++ = b64[((string[i] & 0x3) << 4) |
((int) (string[i + 1] & 0xF0) >> 4)];
*p++ = b64[((string[i + 1] & 0xF) << 2) |
((int) (string[i + 2] & 0xC0) >> 6)];
*p++ = b64[string[i + 2] & 0x3F];
}
if (i < len)
{
*p++ = b64[(string[i] >> 2) & 0x3F];
if (i == (len - 1))
{
*p++ = b64[((string[i] & 0x3) << 4)];
*p++ = '=';
}
else
{
*p++ = b64[((string[i] & 0x3) << 4) |
((int) (string[i + 1] & 0xF0) >> 4)];
*p++ = b64[((string[i + 1] & 0xF) << 2)];
}
*p++ = '=';
}
*p++ = '\0';
return p - encoded;
}
/* This entry point is equivalent to the `crypt' function in Unix
libcs. SHA1 ignores salt. */
char *
__sha_crypt_r (const char *key, const char *salt __attribute__ ((unused)),
char *buffer, int buflen)
{
SHA1_CTX c;
unsigned char md[SHA_DIGESTSIZE];
int l;
if (buflen < (SHA_DIGESTSIZE + 8 + sizeof (sha_salt_prefix)))
{
errno = ERANGE;
return NULL;
}
memset (md, 0, SHA_DIGESTSIZE);
__SHA1Init (&c);
__SHA1Update (&c, key, strlen (key));
__SHA1Final (md, &c);
memcpy (buffer, sha_salt_prefix, sizeof (sha_salt_prefix));
l = base64encode (&buffer[sizeof sha_salt_prefix], md, sizeof (md));
buffer[l + strlen (sha_salt_prefix)] = '\0';
return buffer;
}
char *
__sha_crypt (const char *key, const char *salt)
{
static char buffer[SHA_DIGESTSIZE + 8 + sizeof (sha_salt_prefix)];
static int buflen = sizeof (buffer);
return __sha_crypt_r (key, salt, buffer, buflen);
}
#undef sha_crypt
#undef sha_crypt_r
weak_alias (__sha_crypt, sha_crypt)
weak_alias (__sha_crypt_r, sha_crypt_r)
|