1f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// Copyright 2014 The Chromium Authors. All rights reserved.
2f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// Use of this source code is governed by a BSD-style license that can be
3f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko// found in the LICENSE file.
4f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
5f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#include "crypto/openssl_bio_string.h"
6f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
7f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#include <openssl/bio.h>
8f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko#include <string.h>
9f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
10f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkonamespace crypto {
11f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
12f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkonamespace {
13f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
14f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkoint bio_string_write(BIO* bio, const char* data, int len) {
15f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  reinterpret_cast<std::string*>(bio->ptr)->append(data, len);
16f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  return len;
17f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}
18f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
19f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkoint bio_string_puts(BIO* bio, const char* data) {
20f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // Note: unlike puts(), BIO_puts does not add a newline.
21f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  return bio_string_write(bio, data, strlen(data));
22f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}
23f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
24f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkolong bio_string_ctrl(BIO* bio, int cmd, long num, void* ptr) {
25f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  std::string* str = reinterpret_cast<std::string*>(bio->ptr);
26f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  switch (cmd) {
27f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    case BIO_CTRL_RESET:
28f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko      str->clear();
29f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko      return 1;
30f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    case BIO_C_FILE_SEEK:
31f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko      return -1;
32f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    case BIO_C_FILE_TELL:
33f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko      return str->size();
34f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    case BIO_CTRL_FLUSH:
35f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko      return 1;
36f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    default:
37f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko      return 0;
38f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  }
39f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}
40f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
41f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkoint bio_string_new(BIO* bio) {
42f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  bio->ptr = NULL;
43f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  bio->init = 0;
44f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  return 1;
45f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}
46f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
47f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenkoint bio_string_free(BIO* bio) {
48f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  // The string is owned by the caller, so there's nothing to do here.
49f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  return bio != NULL;
50f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}
51f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
52f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex VakulenkoBIO_METHOD bio_string_methods = {
53f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    // TODO(mattm): Should add some type number too? (bio.h uses 1-24)
54f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    BIO_TYPE_SOURCE_SINK,
55f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    "bio_string",
56f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    bio_string_write,
57f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    NULL, /* read */
58f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    bio_string_puts,
59f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    NULL, /* gets */
60f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    bio_string_ctrl,
61f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    bio_string_new,
62f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    bio_string_free,
63f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    NULL, /* callback_ctrl */
64f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko};
65f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
66f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}  // namespace
67f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
68f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex VakulenkoBIO* BIO_new_string(std::string* out) {
69f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  BIO* bio = BIO_new(&bio_string_methods);
70f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  if (!bio)
71f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko    return bio;
72f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  bio->ptr = out;
73f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  bio->init = 1;
74f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko  return bio;
75f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}
76f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko
77f6024733c0d1eed88f68520b5e6a20b96e212ad6Alex Vakulenko}  // namespace crypto
78