mirror of
https://github.com/clearlinux/clr-installer.git
synced 2026-09-03 04:01:33 +00:00
This is code is still alpha. The Text-based User Interface is undergoing a resign of the layout before beta. Signed-off-by: Mark D Horn <mark.d.horn@intel.com>
103 lines
2.4 KiB
Go
103 lines
2.4 KiB
Go
// Copyright © 2018 Intel Corporation
|
|
//
|
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
package crypt
|
|
|
|
/*
|
|
#cgo LDFLAGS: -lcrypt
|
|
|
|
#define _GNU_SOURCE
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <crypt.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
|
|
#define SALT_SIZE 19 // includes id and separators
|
|
#define ENTROPY_SIZE SALT_SIZE
|
|
#define DICT_SIZE 64
|
|
|
|
const char dict[DICT_SIZE] =
|
|
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
|
|
|
char *__salt_and_crypt(char prefix[3], char *pass, size_t size) {
|
|
int i, fd;
|
|
ssize_t randSize;
|
|
char rand[ENTROPY_SIZE], salt[SALT_SIZE], *enc;
|
|
|
|
// TODO change __salt_and_crypt signature to receive an *int so we can write back
|
|
// the errno if getentropy() fails
|
|
|
|
#if __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 25
|
|
if (getentropy(&rand, ENTROPY_SIZE) != 0) {
|
|
return NULL;
|
|
}
|
|
#else
|
|
fd = open("/dev/urandom", O_RDONLY);
|
|
if (fd < 0) {
|
|
return NULL;
|
|
}
|
|
|
|
randSize = read(fd, rand, ENTROPY_SIZE);
|
|
close(fd);
|
|
if (randSize != ENTROPY_SIZE) {
|
|
return NULL;
|
|
}
|
|
#endif
|
|
|
|
salt[0] = prefix[0];
|
|
salt[1] = prefix[1];
|
|
salt[2] = prefix[2];
|
|
|
|
for (i = 3; i < SALT_SIZE; i++) {
|
|
salt[i] = dict[rand[i] & (DICT_SIZE - 1)];
|
|
}
|
|
|
|
enc = crypt(pass, salt);
|
|
|
|
// Ensure that the rand and salt arrays are zeroed out before returning. The
|
|
// asm statement below will instruct the compiler to not elide the memset() call
|
|
__asm__ __volatile__("" :: "g"(rand) : "memory");
|
|
memset(rand, 0, ENTROPY_SIZE);
|
|
__asm__ __volatile__("" :: "g"(salt) : "memory");
|
|
memset(salt, 0, SALT_SIZE);
|
|
|
|
return enc;
|
|
}
|
|
*/
|
|
import "C"
|
|
import "unsafe"
|
|
|
|
const (
|
|
// SHA512Prefix is the glibc' crypt() identifier for sha512
|
|
SHA512Prefix = "$6$"
|
|
|
|
// SHA512Size is the glibc' crypt() resulting string size
|
|
SHA512Size = 107
|
|
)
|
|
|
|
// Crypt calls glibc' crypt() and getentropy() functions and create a PAM
|
|
// compatible password entry/token. Currently we only support sha512 meaning
|
|
// the algorithm is not selectable/customizable.
|
|
func Crypt(password string) (string, error) {
|
|
cPassword := C.CString(password)
|
|
defer C.free(unsafe.Pointer(cPassword))
|
|
|
|
cPrefix := C.CString(SHA512Prefix)
|
|
defer C.free(unsafe.Pointer(cPrefix))
|
|
|
|
cHashed, err := C.__salt_and_crypt(cPrefix, cPassword, SHA512Size)
|
|
if cHashed == nil {
|
|
return "", err
|
|
}
|
|
|
|
defer func() {
|
|
C.memset(unsafe.Pointer(cHashed), 0, C.strlen(cHashed))
|
|
C.free(unsafe.Pointer(cHashed))
|
|
}()
|
|
|
|
return C.GoString(cHashed), nil
|
|
}
|