11cb0ef41Sopenharmony_ci/*
21cb0ef41Sopenharmony_ci * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
31cb0ef41Sopenharmony_ci *
41cb0ef41Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
51cb0ef41Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
61cb0ef41Sopenharmony_ci * in the file LICENSE in the source distribution or at
71cb0ef41Sopenharmony_ci * https://www.openssl.org/source/license.html
81cb0ef41Sopenharmony_ci */
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ci#include <stdio.h>
111cb0ef41Sopenharmony_ci#include <errno.h>
121cb0ef41Sopenharmony_ci#include "bio_local.h"
131cb0ef41Sopenharmony_ci#include "internal/cryptlib.h"
141cb0ef41Sopenharmony_ci
151cb0ef41Sopenharmony_cistatic int mem_write(BIO *h, const char *buf, int num);
161cb0ef41Sopenharmony_cistatic int mem_read(BIO *h, char *buf, int size);
171cb0ef41Sopenharmony_cistatic int mem_puts(BIO *h, const char *str);
181cb0ef41Sopenharmony_cistatic int mem_gets(BIO *h, char *str, int size);
191cb0ef41Sopenharmony_cistatic long mem_ctrl(BIO *h, int cmd, long arg1, void *arg2);
201cb0ef41Sopenharmony_cistatic int mem_new(BIO *h);
211cb0ef41Sopenharmony_cistatic int secmem_new(BIO *h);
221cb0ef41Sopenharmony_cistatic int mem_free(BIO *data);
231cb0ef41Sopenharmony_cistatic int mem_buf_free(BIO *data);
241cb0ef41Sopenharmony_cistatic int mem_buf_sync(BIO *h);
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_cistatic const BIO_METHOD mem_method = {
271cb0ef41Sopenharmony_ci    BIO_TYPE_MEM,
281cb0ef41Sopenharmony_ci    "memory buffer",
291cb0ef41Sopenharmony_ci    bwrite_conv,
301cb0ef41Sopenharmony_ci    mem_write,
311cb0ef41Sopenharmony_ci    bread_conv,
321cb0ef41Sopenharmony_ci    mem_read,
331cb0ef41Sopenharmony_ci    mem_puts,
341cb0ef41Sopenharmony_ci    mem_gets,
351cb0ef41Sopenharmony_ci    mem_ctrl,
361cb0ef41Sopenharmony_ci    mem_new,
371cb0ef41Sopenharmony_ci    mem_free,
381cb0ef41Sopenharmony_ci    NULL,                      /* mem_callback_ctrl */
391cb0ef41Sopenharmony_ci};
401cb0ef41Sopenharmony_ci
411cb0ef41Sopenharmony_cistatic const BIO_METHOD secmem_method = {
421cb0ef41Sopenharmony_ci    BIO_TYPE_MEM,
431cb0ef41Sopenharmony_ci    "secure memory buffer",
441cb0ef41Sopenharmony_ci    bwrite_conv,
451cb0ef41Sopenharmony_ci    mem_write,
461cb0ef41Sopenharmony_ci    bread_conv,
471cb0ef41Sopenharmony_ci    mem_read,
481cb0ef41Sopenharmony_ci    mem_puts,
491cb0ef41Sopenharmony_ci    mem_gets,
501cb0ef41Sopenharmony_ci    mem_ctrl,
511cb0ef41Sopenharmony_ci    secmem_new,
521cb0ef41Sopenharmony_ci    mem_free,
531cb0ef41Sopenharmony_ci    NULL,                      /* mem_callback_ctrl */
541cb0ef41Sopenharmony_ci};
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_ci/*
571cb0ef41Sopenharmony_ci * BIO memory stores buffer and read pointer
581cb0ef41Sopenharmony_ci * however the roles are different for read only BIOs.
591cb0ef41Sopenharmony_ci * In that case the readp just stores the original state
601cb0ef41Sopenharmony_ci * to be used for reset.
611cb0ef41Sopenharmony_ci */
621cb0ef41Sopenharmony_citypedef struct bio_buf_mem_st {
631cb0ef41Sopenharmony_ci    struct buf_mem_st *buf;   /* allocated buffer */
641cb0ef41Sopenharmony_ci    struct buf_mem_st *readp; /* read pointer */
651cb0ef41Sopenharmony_ci} BIO_BUF_MEM;
661cb0ef41Sopenharmony_ci
671cb0ef41Sopenharmony_ci/*
681cb0ef41Sopenharmony_ci * bio->num is used to hold the value to return on 'empty', if it is 0,
691cb0ef41Sopenharmony_ci * should_retry is not set
701cb0ef41Sopenharmony_ci */
711cb0ef41Sopenharmony_ci
721cb0ef41Sopenharmony_ciconst BIO_METHOD *BIO_s_mem(void)
731cb0ef41Sopenharmony_ci{
741cb0ef41Sopenharmony_ci    return &mem_method;
751cb0ef41Sopenharmony_ci}
761cb0ef41Sopenharmony_ci
771cb0ef41Sopenharmony_ciconst BIO_METHOD *BIO_s_secmem(void)
781cb0ef41Sopenharmony_ci{
791cb0ef41Sopenharmony_ci    return(&secmem_method);
801cb0ef41Sopenharmony_ci}
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_ciBIO *BIO_new_mem_buf(const void *buf, int len)
831cb0ef41Sopenharmony_ci{
841cb0ef41Sopenharmony_ci    BIO *ret;
851cb0ef41Sopenharmony_ci    BUF_MEM *b;
861cb0ef41Sopenharmony_ci    BIO_BUF_MEM *bb;
871cb0ef41Sopenharmony_ci    size_t sz;
881cb0ef41Sopenharmony_ci
891cb0ef41Sopenharmony_ci    if (buf == NULL) {
901cb0ef41Sopenharmony_ci        ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER);
911cb0ef41Sopenharmony_ci        return NULL;
921cb0ef41Sopenharmony_ci    }
931cb0ef41Sopenharmony_ci    sz = (len < 0) ? strlen(buf) : (size_t)len;
941cb0ef41Sopenharmony_ci    if ((ret = BIO_new(BIO_s_mem())) == NULL)
951cb0ef41Sopenharmony_ci        return NULL;
961cb0ef41Sopenharmony_ci    bb = (BIO_BUF_MEM *)ret->ptr;
971cb0ef41Sopenharmony_ci    b = bb->buf;
981cb0ef41Sopenharmony_ci    /* Cast away const and trust in the MEM_RDONLY flag. */
991cb0ef41Sopenharmony_ci    b->data = (void *)buf;
1001cb0ef41Sopenharmony_ci    b->length = sz;
1011cb0ef41Sopenharmony_ci    b->max = sz;
1021cb0ef41Sopenharmony_ci    *bb->readp = *bb->buf;
1031cb0ef41Sopenharmony_ci    ret->flags |= BIO_FLAGS_MEM_RDONLY;
1041cb0ef41Sopenharmony_ci    /* Since this is static data retrying won't help */
1051cb0ef41Sopenharmony_ci    ret->num = 0;
1061cb0ef41Sopenharmony_ci    return ret;
1071cb0ef41Sopenharmony_ci}
1081cb0ef41Sopenharmony_ci
1091cb0ef41Sopenharmony_cistatic int mem_init(BIO *bi, unsigned long flags)
1101cb0ef41Sopenharmony_ci{
1111cb0ef41Sopenharmony_ci    BIO_BUF_MEM *bb = OPENSSL_zalloc(sizeof(*bb));
1121cb0ef41Sopenharmony_ci
1131cb0ef41Sopenharmony_ci    if (bb == NULL)
1141cb0ef41Sopenharmony_ci        return 0;
1151cb0ef41Sopenharmony_ci    if ((bb->buf = BUF_MEM_new_ex(flags)) == NULL) {
1161cb0ef41Sopenharmony_ci        OPENSSL_free(bb);
1171cb0ef41Sopenharmony_ci        return 0;
1181cb0ef41Sopenharmony_ci    }
1191cb0ef41Sopenharmony_ci    if ((bb->readp = OPENSSL_zalloc(sizeof(*bb->readp))) == NULL) {
1201cb0ef41Sopenharmony_ci        BUF_MEM_free(bb->buf);
1211cb0ef41Sopenharmony_ci        OPENSSL_free(bb);
1221cb0ef41Sopenharmony_ci        return 0;
1231cb0ef41Sopenharmony_ci    }
1241cb0ef41Sopenharmony_ci    *bb->readp = *bb->buf;
1251cb0ef41Sopenharmony_ci    bi->shutdown = 1;
1261cb0ef41Sopenharmony_ci    bi->init = 1;
1271cb0ef41Sopenharmony_ci    bi->num = -1;
1281cb0ef41Sopenharmony_ci    bi->ptr = (char *)bb;
1291cb0ef41Sopenharmony_ci    return 1;
1301cb0ef41Sopenharmony_ci}
1311cb0ef41Sopenharmony_ci
1321cb0ef41Sopenharmony_cistatic int mem_new(BIO *bi)
1331cb0ef41Sopenharmony_ci{
1341cb0ef41Sopenharmony_ci    return mem_init(bi, 0L);
1351cb0ef41Sopenharmony_ci}
1361cb0ef41Sopenharmony_ci
1371cb0ef41Sopenharmony_cistatic int secmem_new(BIO *bi)
1381cb0ef41Sopenharmony_ci{
1391cb0ef41Sopenharmony_ci    return mem_init(bi, BUF_MEM_FLAG_SECURE);
1401cb0ef41Sopenharmony_ci}
1411cb0ef41Sopenharmony_ci
1421cb0ef41Sopenharmony_cistatic int mem_free(BIO *a)
1431cb0ef41Sopenharmony_ci{
1441cb0ef41Sopenharmony_ci    BIO_BUF_MEM *bb;
1451cb0ef41Sopenharmony_ci
1461cb0ef41Sopenharmony_ci    if (a == NULL)
1471cb0ef41Sopenharmony_ci        return 0;
1481cb0ef41Sopenharmony_ci
1491cb0ef41Sopenharmony_ci    bb = (BIO_BUF_MEM *)a->ptr;
1501cb0ef41Sopenharmony_ci    if (!mem_buf_free(a))
1511cb0ef41Sopenharmony_ci        return 0;
1521cb0ef41Sopenharmony_ci    OPENSSL_free(bb->readp);
1531cb0ef41Sopenharmony_ci    OPENSSL_free(bb);
1541cb0ef41Sopenharmony_ci    return 1;
1551cb0ef41Sopenharmony_ci}
1561cb0ef41Sopenharmony_ci
1571cb0ef41Sopenharmony_cistatic int mem_buf_free(BIO *a)
1581cb0ef41Sopenharmony_ci{
1591cb0ef41Sopenharmony_ci    if (a == NULL)
1601cb0ef41Sopenharmony_ci        return 0;
1611cb0ef41Sopenharmony_ci
1621cb0ef41Sopenharmony_ci    if (a->shutdown && a->init && a->ptr != NULL) {
1631cb0ef41Sopenharmony_ci        BIO_BUF_MEM *bb = (BIO_BUF_MEM *)a->ptr;
1641cb0ef41Sopenharmony_ci        BUF_MEM *b = bb->buf;
1651cb0ef41Sopenharmony_ci
1661cb0ef41Sopenharmony_ci        if (a->flags & BIO_FLAGS_MEM_RDONLY)
1671cb0ef41Sopenharmony_ci            b->data = NULL;
1681cb0ef41Sopenharmony_ci        BUF_MEM_free(b);
1691cb0ef41Sopenharmony_ci    }
1701cb0ef41Sopenharmony_ci    return 1;
1711cb0ef41Sopenharmony_ci}
1721cb0ef41Sopenharmony_ci
1731cb0ef41Sopenharmony_ci/*
1741cb0ef41Sopenharmony_ci * Reallocate memory buffer if read pointer differs
1751cb0ef41Sopenharmony_ci * NOT FOR RDONLY
1761cb0ef41Sopenharmony_ci */
1771cb0ef41Sopenharmony_cistatic int mem_buf_sync(BIO *b)
1781cb0ef41Sopenharmony_ci{
1791cb0ef41Sopenharmony_ci    if (b != NULL && b->init != 0 && b->ptr != NULL) {
1801cb0ef41Sopenharmony_ci        BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)b->ptr;
1811cb0ef41Sopenharmony_ci
1821cb0ef41Sopenharmony_ci        if (bbm->readp->data != bbm->buf->data) {
1831cb0ef41Sopenharmony_ci            memmove(bbm->buf->data, bbm->readp->data, bbm->readp->length);
1841cb0ef41Sopenharmony_ci            bbm->buf->length = bbm->readp->length;
1851cb0ef41Sopenharmony_ci            bbm->readp->data = bbm->buf->data;
1861cb0ef41Sopenharmony_ci        }
1871cb0ef41Sopenharmony_ci    }
1881cb0ef41Sopenharmony_ci    return 0;
1891cb0ef41Sopenharmony_ci}
1901cb0ef41Sopenharmony_ci
1911cb0ef41Sopenharmony_cistatic int mem_read(BIO *b, char *out, int outl)
1921cb0ef41Sopenharmony_ci{
1931cb0ef41Sopenharmony_ci    int ret = -1;
1941cb0ef41Sopenharmony_ci    BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)b->ptr;
1951cb0ef41Sopenharmony_ci    BUF_MEM *bm = bbm->readp;
1961cb0ef41Sopenharmony_ci
1971cb0ef41Sopenharmony_ci    if (b->flags & BIO_FLAGS_MEM_RDONLY)
1981cb0ef41Sopenharmony_ci        bm = bbm->buf;
1991cb0ef41Sopenharmony_ci    BIO_clear_retry_flags(b);
2001cb0ef41Sopenharmony_ci    ret = (outl >= 0 && (size_t)outl > bm->length) ? (int)bm->length : outl;
2011cb0ef41Sopenharmony_ci    if ((out != NULL) && (ret > 0)) {
2021cb0ef41Sopenharmony_ci        memcpy(out, bm->data, ret);
2031cb0ef41Sopenharmony_ci        bm->length -= ret;
2041cb0ef41Sopenharmony_ci        bm->max -= ret;
2051cb0ef41Sopenharmony_ci        bm->data += ret;
2061cb0ef41Sopenharmony_ci    } else if (bm->length == 0) {
2071cb0ef41Sopenharmony_ci        ret = b->num;
2081cb0ef41Sopenharmony_ci        if (ret != 0)
2091cb0ef41Sopenharmony_ci            BIO_set_retry_read(b);
2101cb0ef41Sopenharmony_ci    }
2111cb0ef41Sopenharmony_ci    return ret;
2121cb0ef41Sopenharmony_ci}
2131cb0ef41Sopenharmony_ci
2141cb0ef41Sopenharmony_cistatic int mem_write(BIO *b, const char *in, int inl)
2151cb0ef41Sopenharmony_ci{
2161cb0ef41Sopenharmony_ci    int ret = -1;
2171cb0ef41Sopenharmony_ci    int blen;
2181cb0ef41Sopenharmony_ci    BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)b->ptr;
2191cb0ef41Sopenharmony_ci
2201cb0ef41Sopenharmony_ci    if (b->flags & BIO_FLAGS_MEM_RDONLY) {
2211cb0ef41Sopenharmony_ci        ERR_raise(ERR_LIB_BIO, BIO_R_WRITE_TO_READ_ONLY_BIO);
2221cb0ef41Sopenharmony_ci        goto end;
2231cb0ef41Sopenharmony_ci    }
2241cb0ef41Sopenharmony_ci    BIO_clear_retry_flags(b);
2251cb0ef41Sopenharmony_ci    if (inl == 0)
2261cb0ef41Sopenharmony_ci        return 0;
2271cb0ef41Sopenharmony_ci    if (in == NULL) {
2281cb0ef41Sopenharmony_ci        ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER);
2291cb0ef41Sopenharmony_ci        goto end;
2301cb0ef41Sopenharmony_ci    }
2311cb0ef41Sopenharmony_ci    blen = bbm->readp->length;
2321cb0ef41Sopenharmony_ci    mem_buf_sync(b);
2331cb0ef41Sopenharmony_ci    if (BUF_MEM_grow_clean(bbm->buf, blen + inl) == 0)
2341cb0ef41Sopenharmony_ci        goto end;
2351cb0ef41Sopenharmony_ci    memcpy(bbm->buf->data + blen, in, inl);
2361cb0ef41Sopenharmony_ci    *bbm->readp = *bbm->buf;
2371cb0ef41Sopenharmony_ci    ret = inl;
2381cb0ef41Sopenharmony_ci end:
2391cb0ef41Sopenharmony_ci    return ret;
2401cb0ef41Sopenharmony_ci}
2411cb0ef41Sopenharmony_ci
2421cb0ef41Sopenharmony_cistatic long mem_ctrl(BIO *b, int cmd, long num, void *ptr)
2431cb0ef41Sopenharmony_ci{
2441cb0ef41Sopenharmony_ci    long ret = 1;
2451cb0ef41Sopenharmony_ci    char **pptr;
2461cb0ef41Sopenharmony_ci    BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)b->ptr;
2471cb0ef41Sopenharmony_ci    BUF_MEM *bm, *bo;            /* bio_mem, bio_other */
2481cb0ef41Sopenharmony_ci    long off, remain;
2491cb0ef41Sopenharmony_ci
2501cb0ef41Sopenharmony_ci    if (b->flags & BIO_FLAGS_MEM_RDONLY) {
2511cb0ef41Sopenharmony_ci        bm = bbm->buf;
2521cb0ef41Sopenharmony_ci        bo = bbm->readp;
2531cb0ef41Sopenharmony_ci    } else {
2541cb0ef41Sopenharmony_ci        bm = bbm->readp;
2551cb0ef41Sopenharmony_ci        bo = bbm->buf;
2561cb0ef41Sopenharmony_ci    }
2571cb0ef41Sopenharmony_ci    off = (bm->data == bo->data) ? 0 : bm->data - bo->data;
2581cb0ef41Sopenharmony_ci    remain = bm->length;
2591cb0ef41Sopenharmony_ci
2601cb0ef41Sopenharmony_ci    switch (cmd) {
2611cb0ef41Sopenharmony_ci    case BIO_CTRL_RESET:
2621cb0ef41Sopenharmony_ci        bm = bbm->buf;
2631cb0ef41Sopenharmony_ci        if (bm->data != NULL) {
2641cb0ef41Sopenharmony_ci            if (!(b->flags & BIO_FLAGS_MEM_RDONLY)) {
2651cb0ef41Sopenharmony_ci                if (!(b->flags & BIO_FLAGS_NONCLEAR_RST)) {
2661cb0ef41Sopenharmony_ci                    memset(bm->data, 0, bm->max);
2671cb0ef41Sopenharmony_ci                    bm->length = 0;
2681cb0ef41Sopenharmony_ci                }
2691cb0ef41Sopenharmony_ci                *bbm->readp = *bbm->buf;
2701cb0ef41Sopenharmony_ci            } else {
2711cb0ef41Sopenharmony_ci                /* For read only case just reset to the start again */
2721cb0ef41Sopenharmony_ci                *bbm->buf = *bbm->readp;
2731cb0ef41Sopenharmony_ci            }
2741cb0ef41Sopenharmony_ci        }
2751cb0ef41Sopenharmony_ci        break;
2761cb0ef41Sopenharmony_ci    case BIO_C_FILE_SEEK:
2771cb0ef41Sopenharmony_ci        if (num < 0 || num > off + remain)
2781cb0ef41Sopenharmony_ci            return -1;   /* Can't see outside of the current buffer */
2791cb0ef41Sopenharmony_ci
2801cb0ef41Sopenharmony_ci        bm->data = (num != 0) ? bo->data + num : bo->data;
2811cb0ef41Sopenharmony_ci        bm->length = bo->length - num;
2821cb0ef41Sopenharmony_ci        bm->max = bo->max - num;
2831cb0ef41Sopenharmony_ci        off = num;
2841cb0ef41Sopenharmony_ci        /* FALLTHRU */
2851cb0ef41Sopenharmony_ci    case BIO_C_FILE_TELL:
2861cb0ef41Sopenharmony_ci        ret = off;
2871cb0ef41Sopenharmony_ci        break;
2881cb0ef41Sopenharmony_ci    case BIO_CTRL_EOF:
2891cb0ef41Sopenharmony_ci        ret = (long)(bm->length == 0);
2901cb0ef41Sopenharmony_ci        break;
2911cb0ef41Sopenharmony_ci    case BIO_C_SET_BUF_MEM_EOF_RETURN:
2921cb0ef41Sopenharmony_ci        b->num = (int)num;
2931cb0ef41Sopenharmony_ci        break;
2941cb0ef41Sopenharmony_ci    case BIO_CTRL_INFO:
2951cb0ef41Sopenharmony_ci        ret = (long)bm->length;
2961cb0ef41Sopenharmony_ci        if (ptr != NULL) {
2971cb0ef41Sopenharmony_ci            pptr = (char **)ptr;
2981cb0ef41Sopenharmony_ci            *pptr = (char *)(bm->data);
2991cb0ef41Sopenharmony_ci        }
3001cb0ef41Sopenharmony_ci        break;
3011cb0ef41Sopenharmony_ci    case BIO_C_SET_BUF_MEM:
3021cb0ef41Sopenharmony_ci        mem_buf_free(b);
3031cb0ef41Sopenharmony_ci        b->shutdown = (int)num;
3041cb0ef41Sopenharmony_ci        bbm->buf = ptr;
3051cb0ef41Sopenharmony_ci        *bbm->readp = *bbm->buf;
3061cb0ef41Sopenharmony_ci        break;
3071cb0ef41Sopenharmony_ci    case BIO_C_GET_BUF_MEM_PTR:
3081cb0ef41Sopenharmony_ci        if (ptr != NULL) {
3091cb0ef41Sopenharmony_ci            if (!(b->flags & BIO_FLAGS_MEM_RDONLY))
3101cb0ef41Sopenharmony_ci                mem_buf_sync(b);
3111cb0ef41Sopenharmony_ci            bm = bbm->buf;
3121cb0ef41Sopenharmony_ci            pptr = (char **)ptr;
3131cb0ef41Sopenharmony_ci            *pptr = (char *)bm;
3141cb0ef41Sopenharmony_ci        }
3151cb0ef41Sopenharmony_ci        break;
3161cb0ef41Sopenharmony_ci    case BIO_CTRL_GET_CLOSE:
3171cb0ef41Sopenharmony_ci        ret = (long)b->shutdown;
3181cb0ef41Sopenharmony_ci        break;
3191cb0ef41Sopenharmony_ci    case BIO_CTRL_SET_CLOSE:
3201cb0ef41Sopenharmony_ci        b->shutdown = (int)num;
3211cb0ef41Sopenharmony_ci        break;
3221cb0ef41Sopenharmony_ci    case BIO_CTRL_WPENDING:
3231cb0ef41Sopenharmony_ci        ret = 0L;
3241cb0ef41Sopenharmony_ci        break;
3251cb0ef41Sopenharmony_ci    case BIO_CTRL_PENDING:
3261cb0ef41Sopenharmony_ci        ret = (long)bm->length;
3271cb0ef41Sopenharmony_ci        break;
3281cb0ef41Sopenharmony_ci    case BIO_CTRL_DUP:
3291cb0ef41Sopenharmony_ci    case BIO_CTRL_FLUSH:
3301cb0ef41Sopenharmony_ci        ret = 1;
3311cb0ef41Sopenharmony_ci        break;
3321cb0ef41Sopenharmony_ci    case BIO_CTRL_PUSH:
3331cb0ef41Sopenharmony_ci    case BIO_CTRL_POP:
3341cb0ef41Sopenharmony_ci    default:
3351cb0ef41Sopenharmony_ci        ret = 0;
3361cb0ef41Sopenharmony_ci        break;
3371cb0ef41Sopenharmony_ci    }
3381cb0ef41Sopenharmony_ci    return ret;
3391cb0ef41Sopenharmony_ci}
3401cb0ef41Sopenharmony_ci
3411cb0ef41Sopenharmony_cistatic int mem_gets(BIO *bp, char *buf, int size)
3421cb0ef41Sopenharmony_ci{
3431cb0ef41Sopenharmony_ci    int i, j;
3441cb0ef41Sopenharmony_ci    int ret = -1;
3451cb0ef41Sopenharmony_ci    char *p;
3461cb0ef41Sopenharmony_ci    BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)bp->ptr;
3471cb0ef41Sopenharmony_ci    BUF_MEM *bm = bbm->readp;
3481cb0ef41Sopenharmony_ci
3491cb0ef41Sopenharmony_ci    if (bp->flags & BIO_FLAGS_MEM_RDONLY)
3501cb0ef41Sopenharmony_ci        bm = bbm->buf;
3511cb0ef41Sopenharmony_ci    BIO_clear_retry_flags(bp);
3521cb0ef41Sopenharmony_ci    j = bm->length;
3531cb0ef41Sopenharmony_ci    if ((size - 1) < j)
3541cb0ef41Sopenharmony_ci        j = size - 1;
3551cb0ef41Sopenharmony_ci    if (j <= 0) {
3561cb0ef41Sopenharmony_ci        *buf = '\0';
3571cb0ef41Sopenharmony_ci        return 0;
3581cb0ef41Sopenharmony_ci    }
3591cb0ef41Sopenharmony_ci    p = bm->data;
3601cb0ef41Sopenharmony_ci    for (i = 0; i < j; i++) {
3611cb0ef41Sopenharmony_ci        if (p[i] == '\n') {
3621cb0ef41Sopenharmony_ci            i++;
3631cb0ef41Sopenharmony_ci            break;
3641cb0ef41Sopenharmony_ci        }
3651cb0ef41Sopenharmony_ci    }
3661cb0ef41Sopenharmony_ci
3671cb0ef41Sopenharmony_ci    /*
3681cb0ef41Sopenharmony_ci     * i is now the max num of bytes to copy, either j or up to
3691cb0ef41Sopenharmony_ci     * and including the first newline
3701cb0ef41Sopenharmony_ci     */
3711cb0ef41Sopenharmony_ci
3721cb0ef41Sopenharmony_ci    i = mem_read(bp, buf, i);
3731cb0ef41Sopenharmony_ci    if (i > 0)
3741cb0ef41Sopenharmony_ci        buf[i] = '\0';
3751cb0ef41Sopenharmony_ci    ret = i;
3761cb0ef41Sopenharmony_ci    return ret;
3771cb0ef41Sopenharmony_ci}
3781cb0ef41Sopenharmony_ci
3791cb0ef41Sopenharmony_cistatic int mem_puts(BIO *bp, const char *str)
3801cb0ef41Sopenharmony_ci{
3811cb0ef41Sopenharmony_ci    int n, ret;
3821cb0ef41Sopenharmony_ci
3831cb0ef41Sopenharmony_ci    n = strlen(str);
3841cb0ef41Sopenharmony_ci    ret = mem_write(bp, str, n);
3851cb0ef41Sopenharmony_ci    /* memory semantics is that it will always work */
3861cb0ef41Sopenharmony_ci    return ret;
3871cb0ef41Sopenharmony_ci}
388