Crypt-PQClean-Sign

 view release on metacpan or  search on metacpan

pqclean/common/randombytes.c  view on Meta::CPAN

        }
    }
    do {
        retcode = close(fd);
    } while (retcode == -1 && errno == EINTR);
    if (strategy == PROC) {
        do {
            retcode = fclose(proc_file);
        } while (retcode == -1 && errno == EINTR);
    }
    if (retcode_error != 0) {
        return retcode_error;
    }
    return retcode;
}

static int randombytes_linux_randombytes_urandom(void *buf, size_t n) {
    int fd;
    size_t offset = 0, count;
    ssize_t tmp;
    do {
        fd = open("/dev/urandom", O_RDONLY);
    } while (fd == -1 && errno == EINTR);
    if (fd == -1) {
        return -1;
    }
    if (randombytes_linux_wait_for_entropy(fd) == -1) {
        return -1;
    }

    while (n > 0) {
        count = n <= SSIZE_MAX ? n : SSIZE_MAX;
        tmp = read(fd, (char *)buf + offset, count);
        if (tmp == -1 && (errno == EAGAIN || errno == EINTR)) {
            continue;
        }
        if (tmp == -1) {
            return -1;    /* Unrecoverable IO error */
        }
        offset += tmp;
        n -= tmp;
    }
    close(fd);
    assert(n == 0);
    return 0;
}
#endif /* defined(__linux__) && !defined(SYS_getrandom) */

#if defined(BSD)
static int randombytes_bsd_randombytes(void *buf, size_t n) {
    arc4random_buf(buf, n);
    return 0;
}
#endif /* defined(BSD) */

#if defined(__EMSCRIPTEN__)
static int randombytes_js_randombytes_nodejs(void *buf, size_t n) {
    const int ret = EM_ASM_INT({
        var crypto;
        try {
            crypto = require('crypto');
        } catch (error) {
            return -2;
        }
        try {
            writeArrayToMemory(crypto.randomBytes($1), $0);
            return 0;
        } catch (error) {
            return -1;
        }
    }, buf, n);
    switch (ret) {
    case 0:
        return 0;
    case -1:
        errno = EINVAL;
        return -1;
    case -2:
        errno = ENOSYS;
        return -1;
    }
    assert(false); // Unreachable
}
#endif /* defined(__EMSCRIPTEN__) */

int randombytes(uint8_t *output, size_t n) {
    void *buf = (void *)output;
    #if defined(__EMSCRIPTEN__)
    return randombytes_js_randombytes_nodejs(buf, n);
    #elif defined(__linux__)
    # if defined(USE_GLIBC)
    /* Use getrandom system call */
    return randombytes_linux_randombytes_getrandom(buf, n);
    # elif defined(SYS_getrandom)
    /* Use getrandom system call */
    return randombytes_linux_randombytes_getrandom(buf, n);
    # else
    /* When we have enough entropy, we can read from /dev/urandom */
    return randombytes_linux_randombytes_urandom(buf, n);
    # endif
    #elif defined(BSD)
    /* Use arc4random system call */
    return randombytes_bsd_randombytes(buf, n);
    #elif defined(_WIN32)
    /* Use windows API */
    return randombytes_win32_randombytes(buf, n);
    #elif defined(__wasi__)
    /* Use WASI */
    return randombytes_wasi_randombytes(buf, n);
    #else
# error "randombytes(...) is not supported on this platform"
    #endif
}



( run in 3.134 seconds using v1.01-cache-2.11-cpan-995e09ba956 )