Пример #1
0
/* Load the private key.
 * @mand should be non zero if it is required to read a private key.
 */
gnutls_x509_privkey_t
load_x509_private_key (int mand, common_info_st * info)
{
  gnutls_x509_privkey_t key;
  int ret;
  gnutls_datum_t dat;
  size_t size;
  unsigned int flags = 0;
  const char* pass;

  if (!info->privkey && !mand)
    return NULL;

  if (info->privkey == NULL)
    error (EXIT_FAILURE, 0, "missing --load-privkey");

  ret = gnutls_x509_privkey_init (&key);
  if (ret < 0)
    error (EXIT_FAILURE, 0, "privkey_init: %s", gnutls_strerror (ret));

  dat.data = (void*)read_binary_file (info->privkey, &size);
  dat.size = size;

  if (!dat.data)
    error (EXIT_FAILURE, errno, "reading --load-privkey: %s", info->privkey);

  if (info->pkcs8)
    {
      pass = get_password (info, &flags, 0);
      ret =
        gnutls_x509_privkey_import_pkcs8 (key, &dat, info->incert_format,
                                          pass, flags);
    }
  else
    {
      ret = gnutls_x509_privkey_import2 (key, &dat, info->incert_format, NULL, 0);
      if (ret == GNUTLS_E_DECRYPTION_FAILED)
        {
          pass = get_password (info, &flags, 0);
          ret = gnutls_x509_privkey_import2 (key, &dat, info->incert_format, pass, flags);
        }
    }

  free (dat.data);

  if (ret == GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR)
    {
      error (EXIT_FAILURE, 0,
             "import error: could not find a valid PEM header; "
             "check if your key is PKCS #12 encoded");
    }

  if (ret < 0)
    error (EXIT_FAILURE, 0, "importing --load-privkey: %s: %s",
           info->privkey, gnutls_strerror (ret));

  return key;
}
Пример #2
0
static int import_Key(QWidget * w, gnutls_x509_privkey_t * privkey,
                      gnutls_datum_t * raw)
{
    int ret;

    if (raw->size == 0)
        return -1;

    gnutls_x509_privkey_init(privkey);

    ret =
        gnutls_x509_privkey_import2(*privkey, raw, GNUTLS_X509_FMT_PEM, NULL,
                                    0);
    if (ret == GNUTLS_E_DECRYPTION_FAILED && w != NULL) {
        bool ok;
        QString text;
        text =
            QInputDialog::getText(w,
                                  QLatin1String
                                  ("This file requires a password"),
                                  QLatin1String("Please enter your password"),
                                  QLineEdit::Password, QString(), &ok);
        if (!ok) {
            ret = -1;
            goto fail;
        }

        ret =
            gnutls_x509_privkey_import2(*privkey, raw, GNUTLS_X509_FMT_PEM,
                                        text.toAscii().data(), 0);
    }

    if (ret == GNUTLS_E_BASE64_DECODING_ERROR
            || ret == GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR)
        ret = gnutls_x509_privkey_import(*privkey, raw, GNUTLS_X509_FMT_DER);
    if (ret < 0) {
        goto fail;
    }

    return 0;
fail:
    gnutls_x509_privkey_deinit(*privkey);
    *privkey = NULL;
    return ret;
}
Пример #3
0
PrivateKey::PrivateKey(const Blob& import)
{
    if (gnutls_global_init() != GNUTLS_E_SUCCESS)
        throw CryptoException("Can't initialize GnuTLS.");
    int err = gnutls_x509_privkey_init(&x509_key);
    if (err != GNUTLS_E_SUCCESS)
        throw CryptoException("Can't initialize private key !");

    const gnutls_datum_t dt {(uint8_t*)import.data(), static_cast<unsigned>(import.size())};
    err = gnutls_x509_privkey_import2(x509_key, &dt, GNUTLS_X509_FMT_PEM, nullptr, GNUTLS_PKCS_PLAIN);
    if (err != GNUTLS_E_SUCCESS)
        err = gnutls_x509_privkey_import2(x509_key, &dt, GNUTLS_X509_FMT_DER, nullptr, GNUTLS_PKCS_PLAIN);
    if (err != GNUTLS_E_SUCCESS) {
        gnutls_x509_privkey_deinit(x509_key);
        throw CryptoException("Can't load private key !");
    }

    gnutls_privkey_init(&key);
    if (gnutls_privkey_import_x509(key, x509_key, GNUTLS_PRIVKEY_IMPORT_COPY) != GNUTLS_E_SUCCESS) {
        throw CryptoException("Can't load generic private key !");
    }
}
Пример #4
0
/**
 * gnutls_privkey_import_x509_raw:
 * @pkey: The private key
 * @data: The private key data to be imported
 * @format: The format of the private key
 * @password: A password (optional)
 * @flags: an ORed sequence of gnutls_pkcs_encrypt_flags_t
 *
 * This function will import the given private key to the abstract
 * #gnutls_privkey_t type. 
 *
 * The supported formats are basic unencrypted key, PKCS8, PKCS12, 
 * and the openssl format.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 *
 * Since: 3.1.0
 **/
int gnutls_privkey_import_x509_raw(gnutls_privkey_t pkey,
				   const gnutls_datum_t * data,
				   gnutls_x509_crt_fmt_t format,
				   const char *password, unsigned int flags)
{
	gnutls_x509_privkey_t xpriv;
	int ret;

	ret = gnutls_x509_privkey_init(&xpriv);
	if (ret < 0)
		return gnutls_assert_val(ret);

	if (pkey->pin.cb) {
		gnutls_x509_privkey_set_pin_function(xpriv, pkey->pin.cb,
						     pkey->pin.data);
	}

	ret = gnutls_x509_privkey_import2(xpriv, data, format, password, flags);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	ret =
	    gnutls_privkey_import_x509(pkey, xpriv,
				       GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	return 0;

 cleanup:
	gnutls_x509_privkey_deinit(xpriv);

	return ret;
}
Пример #5
0
void doit(void)
{
#ifdef ENABLE_NON_SUITEB_CURVES
	const char *filename, *password = "******";
	gnutls_pkcs12_t pkcs12;
	gnutls_datum_t data;
	gnutls_x509_crt_t *chain, *extras;
	unsigned int chain_size = 0, extras_size = 0, i;
	gnutls_x509_privkey_t pkey;
	int ret;

	ret = global_init();
	if (ret < 0)
		fail("global_init failed %d\n", ret);

	gnutls_global_set_log_function(tls_log_func);
	if (debug)
		gnutls_global_set_log_level(2);

	ret = gnutls_pkcs12_init(&pkcs12);
	if (ret < 0)
		fail("initialization failed: %s\n", gnutls_strerror(ret));

	filename = getenv("PKCS12_MANY_CERTS_FILE");

	if (!filename)
		filename = "pkcs12-decode/pkcs12_5certs.p12";

	if (debug)
		success
		    ("Reading PKCS#12 blob from `%s' using password `%s'.\n",
		     filename, password);

	ret = gnutls_load_file(filename, &data);
	if (ret < 0)
		fail("cannot open file");

	ret = gnutls_pkcs12_import(pkcs12, &data, GNUTLS_X509_FMT_DER, 0);
	if (ret < 0)
		fail("pkcs12_import failed %d: %s\n", ret,
		     gnutls_strerror(ret));

	if (debug)
		success("Read file OK\n");

	ret =
	    gnutls_pkcs12_simple_parse(pkcs12, password, &pkey, &chain,
					&chain_size, &extras, &extras_size,
					NULL, 0);
	if (ret < 0)
		fail("pkcs12_simple_parse failed %d: %s\n", ret,
		     gnutls_strerror(ret));

	if (chain_size != 1)
		fail("chain size (%u) should have been 1\n", chain_size);

	if (extras_size != 4)
		fail("extras size (%u) should have been 4\n", extras_size);

	if (debug) {
		char dn[512];
		size_t dn_size;

		dn_size = sizeof(dn);
		ret = gnutls_x509_crt_get_dn(chain[0], dn, &dn_size);
		if (ret < 0)
			fail("crt_get_dn failed %d: %s\n", ret,
			     gnutls_strerror(ret));

		success("dn: %s\n", dn);

		dn_size = sizeof(dn);
		ret =
		    gnutls_x509_crt_get_issuer_dn(chain[0], dn, &dn_size);
		if (ret < 0)
			fail("crt_get_dn failed %d: %s\n", ret,
			     gnutls_strerror(ret));

		success("issuer dn: %s\n", dn);
	}

	gnutls_pkcs12_deinit(pkcs12);
	gnutls_x509_privkey_deinit(pkey);

	for (i = 0; i < chain_size; i++)
		gnutls_x509_crt_deinit(chain[i]);
	gnutls_free(chain);

	for (i = 0; i < extras_size; i++)
		gnutls_x509_crt_deinit(extras[i]);
	gnutls_free(extras);

	/* Try gnutls_x509_privkey_import2() */
	ret = gnutls_x509_privkey_init(&pkey);
	if (ret < 0)
		fail("gnutls_x509_privkey_init failed %d: %s\n", ret,
		     gnutls_strerror(ret));

	ret =
	    gnutls_x509_privkey_import2(pkey, &data, GNUTLS_X509_FMT_DER,
					password, 0);
	if (ret < 0)
		fail("gnutls_x509_privkey_import2 failed %d: %s\n", ret,
		     gnutls_strerror(ret));
	gnutls_x509_privkey_deinit(pkey);

	free(data.data);

	gnutls_global_deinit();
#else
	exit(77);
#endif
}
Пример #6
0
int
main(int argc, char *argv[])
{
    int ret = 1;
    int i;
    gnutls_pubkey_t pubkey = NULL;
    gnutls_x509_privkey_t sigkey = NULL;
    gnutls_x509_crt_t sigcert = NULL;
    gnutls_x509_crt_t crt = NULL;
    const char *pubkey_filename = NULL;
    const char *sigkey_filename = NULL;
    const char *cert_filename = NULL;
    const char *modulus_str = NULL;
    const char *issuercert_filename = NULL;
    unsigned char *modulus_bin = NULL;
    int modulus_len = 0;
    gnutls_datum_t datum = { NULL, 0},  out = { NULL, 0};
    int serial = 1;
    time_t now;
    int err;
    FILE *cert_file;
    char *subject = NULL;
    const char *error = NULL;
    int days = 365;
    char *sigkeypass = NULL;
    uint32_t ser_number;
    long int exponent = 0x10001;
    bool write_pem = false;
    uint8_t id[512];
    size_t id_size = sizeof(id);
    enum cert_type_t certtype = CERT_TYPE_EK;
    const char *oid;
    unsigned int key_usage;
    char *tpm_manufacturer = NULL;
    char *tpm_version = NULL;
    char *tpm_model = NULL;
    char *platf_manufacturer = NULL;
    char *platf_version = NULL;
    char *platf_model = NULL;

    i = 1;
    while (i < argc) {
        if (!strcmp(argv[i], "--pubkey")) {
            i++;
            if (i == argc) {
                fprintf(stderr, "Missing argument for --pubkey.\n");
                goto cleanup;
            }
            pubkey_filename = argv[i];
        } else if (!strcmp(argv[i], "--modulus")) {
            i++;
            if (i == argc) {
                fprintf(stderr, "Missing argument for --modulus.\n");
                goto cleanup;
            }
            modulus_str = argv[i];
            if (!(modulus_bin = hex_str_to_bin(modulus_str, &modulus_len))) {
                goto cleanup;
            }
        } else if (!strcmp(argv[i], "--exponent")) {
            i++;
            if (i == argc) {
                fprintf(stderr, "Missing argument for --exponent.\n");
                goto cleanup;
            }
            exponent = strtol(argv[i], NULL, 0);
            if (exponent == 0) {
                fprintf(stderr, "Exponent is wrong and cannot be 0.\n");
                goto cleanup;
            }
            if (exponent > UINT_MAX) {
                fprintf(stderr, "Exponent must fit into 32bits.\n");
                goto cleanup;
            }
        } else if (!strcmp(argv[i], "--signkey")) {
            i++;
            if (i == argc) {
                fprintf(stderr, "Missing argument for --signkey.\n");
                goto cleanup;
            }
            sigkey_filename = argv[i];
        } else if (!strcmp(argv[i], "--signkey-password")) {
            i++;
            if (i == argc) {
                fprintf(stderr, "Missing argument for --signkey-password.\n");
                goto cleanup;
            }
            sigkeypass = argv[i];
        } else if (!strcmp(argv[i], "--issuercert")) {
            i++;
            if (i == argc) {
                fprintf(stderr, "Missing argument for --issuercert.\n");
                goto cleanup;
            }
            issuercert_filename = argv[i];
        } else if (!strcmp(argv[i], "--out-cert")) {
            i++;
            if (i == argc) {
                fprintf(stderr, "Missing argument for --out-cert.\n");
                goto cleanup;
            }
            cert_filename = argv[i];
        } else if (!strcmp(argv[i], "--subject")) {
            i++;
            if (i == argc) {
                fprintf(stderr, "Missing argument for --subject.\n");
                goto cleanup;
            }
            subject = argv[i];
        } else if (!strcmp(argv[i], "--days")) {
            i++;
            if (i == argc) {
                fprintf(stderr, "Missing argument for --days.\n");
                goto cleanup;
            }
            days = atoi(argv[i]);
        } else if (!strcmp(argv[i], "--serial")) {
            i++;
            if (i == argc) {
                fprintf(stderr, "Missing argument for --serial.\n");
                goto cleanup;
            }
            serial = atoi(argv[i]);
        } else if (!strcmp(argv[i], "--type")) {
            i++;
            if (i == argc) {
                fprintf(stderr, "Missing argument for --type.\n");
                goto cleanup;
            }
            if (!strcasecmp(argv[i], "ek")) {
                certtype = CERT_TYPE_EK;
            } else if (!strcasecmp(argv[i], "platform")) {
                certtype = CERT_TYPE_PLATFORM;
//            } else if (!strcasecmp(argv[i], "aik")) {
//                /* AIK cert needs EK cert as input */
//                certtype = CERT_TYPE_AIK;
            } else {
                fprintf(stderr, "Unknown certificate type '%s'.\n",
                        argv[i]);
                goto cleanup;
            }
        } else if (!strcmp(argv[i], "--tpm-manufacturer")) {
            i++;
            if (i == argc) {
                fprintf(stderr, "Missing argument for --tpm-manufacturer.\n");
                goto cleanup;
            }
            tpm_manufacturer = argv[i];
        } else if (!strcmp(argv[i], "--tpm-model")) {
            i++;
            if (i == argc) {
                fprintf(stderr, "Missing argument for --tpm-model.\n");
                goto cleanup;
            }
            tpm_model = argv[i];
        } else if (!strcmp(argv[i], "--tpm-version")) {
            i++;
            if (i == argc) {
                fprintf(stderr, "Missing argument for --tpm-version.\n");
                goto cleanup;
            }
            tpm_version = argv[i];
        } else if (!strcmp(argv[i], "--platform-manufacturer")) {
            i++;
            if (i == argc) {
                fprintf(stderr, "Missing argument for --platform-manufacturer.\n");
                goto cleanup;
            }
            platf_manufacturer = argv[i];
        } else if (!strcmp(argv[i], "--platform-model")) {
            i++;
            if (i == argc) {
                fprintf(stderr, "Missing argument for --platform-model.\n");
                goto cleanup;
            }
            platf_model = argv[i];
        } else if (!strcmp(argv[i], "--platform-version")) {
            i++;
            if (i == argc) {
                fprintf(stderr, "Missing argument for --platform-version.\n");
                goto cleanup;
            }
            platf_version = argv[i];
        } else if (!strcmp(argv[i], "--pem")) {
            write_pem = true;
        } else if (!strcmp(argv[i], "--help")) {
            usage(argv[0]);
            exit(0);
        } else {
            fprintf(stderr, "Unknown command line parameter '%s'.\n", argv[i]);
            usage(argv[0]);
            exit(1);
        }
        i++;
    }
    
    ser_number = htonl(serial);

    if (pubkey_filename == NULL && modulus_bin == NULL) {
        fprintf(stderr, "Missing public EK file and modulus.\n");
        usage(argv[0]);
        goto cleanup;
    }

    if (issuercert_filename == NULL) {
        fprintf(stderr, "The issuer certificate name is required.\n");
        goto cleanup;
    }

    switch (certtype) {
    case CERT_TYPE_EK:
    case CERT_TYPE_PLATFORM:
        if (tpm_manufacturer == NULL ||
            tpm_model == NULL ||
            tpm_version == NULL) {
            fprintf(stderr, "--tpm-manufacturer and --tpm-model and "
                            "--tpm version "
                            "must all be provided\n");
            goto cleanup;
        }
        break;
    case CERT_TYPE_AIK:
        break;
    }

    switch (certtype) {
    case CERT_TYPE_PLATFORM:
        if (platf_manufacturer == NULL ||
            platf_model == NULL ||
            platf_version == NULL) {
            fprintf(stderr, "--platform-manufacturer and --platform-model and "
                            "--platform version "
                            "must all be provided\n");
            goto cleanup;
        }
        break;
    case CERT_TYPE_EK:
    case CERT_TYPE_AIK:
        break;
    }

    err = gnutls_global_init();
    if (err < 0) {
            fprintf(stderr, "gnutls_global_init failed.\n");
            goto cleanup;
    }
    gnutls_x509_privkey_init(&sigkey);

    if (pubkey_filename) {
        gnutls_pubkey_init(&pubkey);

        err = gnutls_load_file(pubkey_filename, &datum);
        if (err != GNUTLS_E_SUCCESS) {
            fprintf(stderr, "Could not open file for EK public key: %s\n",
                strerror(errno));
            goto cleanup;
        }

        err = gnutls_pubkey_import(pubkey, &datum, GNUTLS_X509_FMT_PEM);
        gnutls_free(datum.data);
        datum.data = NULL;
        if (err != GNUTLS_E_SUCCESS) {
            fprintf(stderr, "Could not import EK.\n");
            goto cleanup;
        }
    } else {
        pubkey = create_rsa_from_modulus(modulus_bin, modulus_len,
                                         exponent);
        free(modulus_bin);
        modulus_bin = NULL;

        if (pubkey == NULL)
            goto cleanup;
    }

    /* all types of keys must have pubkey set now otherwise the signing
       will not work */

    if (sigkey_filename == NULL) {
        fprintf(stderr, "Missing signature key.\n");
        usage(argv[0]);
        exit(1);
    }

#define CHECK_GNUTLS_ERROR(_err, _msg, ...) \
if (_err != GNUTLS_E_SUCCESS) {             \
    fprintf(stderr, _msg, __VA_ARGS__);     \
    goto cleanup;                           \
}

    err = gnutls_load_file(sigkey_filename, &datum);
    CHECK_GNUTLS_ERROR(err, "Could not read signing key from file %s: %s\n",
                       sigkey_filename, gnutls_strerror(err));

    if (sigkeypass) {
        err = gnutls_x509_privkey_import2(sigkey, &datum, GNUTLS_X509_FMT_PEM,
                                          sigkeypass, 0);
    } else {
        err = gnutls_x509_privkey_import(sigkey, &datum, GNUTLS_X509_FMT_PEM);
    }
    gnutls_free(datum.data);
    datum.data = NULL;
    CHECK_GNUTLS_ERROR(err, "Could not import signing key : %s\n",
                       gnutls_strerror(err));

    err = gnutls_load_file(issuercert_filename, &datum);
    CHECK_GNUTLS_ERROR(err, "Could not read certificate from file %s : %s\n",
                       issuercert_filename, gnutls_strerror(err));

    gnutls_x509_crt_init(&sigcert);

    err = gnutls_x509_crt_import(sigcert, &datum, GNUTLS_X509_FMT_PEM);
    gnutls_free(datum.data);
    datum.data = NULL;
    CHECK_GNUTLS_ERROR(err, "Could not import issuer certificate: %s\n",
                       gnutls_strerror(err));

    err = gnutls_x509_crt_init(&crt);
    CHECK_GNUTLS_ERROR(err, "CRT init failed: %s\n", gnutls_strerror(err))

    /* 3.5.1 Version */
    err = gnutls_x509_crt_set_version(crt, 3);
    CHECK_GNUTLS_ERROR(err, "Could not set version on CRT: %s\n",
                       gnutls_strerror(err))

    /* 3.5.2 Serial Number */
    err = gnutls_x509_crt_set_serial(crt, &ser_number, sizeof(ser_number));
    CHECK_GNUTLS_ERROR(err, "Could not set serial on CRT: %s\n",
                       gnutls_strerror(err))

    /* 3.5.5 Validity */
    now = time(NULL);
    err = gnutls_x509_crt_set_activation_time(crt, now);
    CHECK_GNUTLS_ERROR(err, "Could not set activation time on CRT: %s\n",
                       gnutls_strerror(err))

    err = gnutls_x509_crt_set_expiration_time(crt,
             now + (time_t)days * 24 * 60 * 60);
    CHECK_GNUTLS_ERROR(err, "Could not set expiration time on CRT: %s\n",
                       gnutls_strerror(err))

    /* 3.5.6 Subject -- should be empty, but we allow it anyway */
    if (subject) {
        err = gnutls_x509_crt_set_dn(crt, subject, &error);
        CHECK_GNUTLS_ERROR(err,
                           "Could not set DN on CRT: %s\n"
                           "DN '%s must be fault after %s\n.'",
                           gnutls_strerror(err),
                           subject, error)
    }

    /* 3.5.7 Public Key Info */
    switch (certtype) {
    case CERT_TYPE_EK:
        oid = "1.2.840.113549.1.1.7";
        break;
    case CERT_TYPE_PLATFORM:
        oid = NULL;
        break;
    case CERT_TYPE_AIK:
        oid = "1.2.840.113549.1.1.1";
        break;
    default:
        fprintf(stderr, "Internal error: unhandle case in line %d\n",
                __LINE__);
        goto cleanup;
    }
    if (oid) {
        err = gnutls_x509_crt_set_key_purpose_oid(crt, oid, 0);
        CHECK_GNUTLS_ERROR(err, "Could not set key purpose on CRT: %s\n",
                           gnutls_strerror(err))
    }

    /* 3.5.8 Certificate Policies -- skip since not mandated */
    /* 3.5.9 Subject Alternative Names -- missing code */
    err = create_tpm_manufacturer_info(tpm_manufacturer, tpm_model,
                                       tpm_version, &datum);
    if (!err && datum.size > 0) {
        /*
         * GNUTLS's write_new_general_name can only handle a few GNUTLS_SAN_*
         * -> we have to use GNUTLS_SAN_URI
         */
        err = gnutls_x509_crt_set_subject_alt_name(crt,
                                                   GNUTLS_SAN_URI,
                                                   datum.data, datum.size,
                                                   GNUTLS_FSAN_SET);
        CHECK_GNUTLS_ERROR(err, "Could not set subject alt name: %s\n",
                           gnutls_strerror(err))
    }
Пример #7
0
/* Loads a x509 private key list
 */
gnutls_x509_privkey_t *load_privkey_list(int mand, size_t * privkey_size,
					 common_info_st * info)
{
	static gnutls_x509_privkey_t key[MAX_KEYS];
	char *ptr;
	int ret, i;
	gnutls_datum_t dat, file_data;
	int ptr_size;
	unsigned int flags = 0;
	const char *pass;

	*privkey_size = 0;
	fprintf(stderr, "Loading private key list...\n");

	if (info->privkey == NULL) {
		if (mand) {
			fprintf(stderr, "missing --load-privkey");
			exit(1);
		} else
			return NULL;
	}

	ret = gnutls_load_file(info->privkey, &file_data);
	if (ret < 0) {
		fprintf(stderr, "%s", info->privkey);
		exit(1);
	}

	ptr = (void *) file_data.data;
	ptr_size = file_data.size;

	for (i = 0; i < MAX_KEYS; i++) {
		ret = gnutls_x509_privkey_init(&key[i]);
		if (ret < 0) {
			fprintf(stderr, "privkey_init: %s",
				gnutls_strerror(ret));
			exit(1);
		}

		dat.data = (void *) ptr;
		dat.size = ptr_size;

		ret =
		    gnutls_x509_privkey_import2(key[i], &dat,
						info->incert_format, NULL,
						0);
		if (ret == GNUTLS_E_DECRYPTION_FAILED) {
			pass = get_password(info, &flags, 0);
			ret =
			    gnutls_x509_privkey_import2(key[i], &dat,
							info->
							incert_format,
							pass, flags);
		}

		if (ret < 0 && *privkey_size > 0)
			break;
		if (ret < 0) {
			fprintf(stderr, "privkey_import: %s",
				gnutls_strerror(ret));
			exit(1);
		}

		(*privkey_size)++;

		if (info->incert_format != GNUTLS_X509_FMT_PEM)
			break;

		ptr = strstr(ptr, "---END");
		if (ptr == NULL)
			break;
		ptr++;

		ptr_size = file_data.size;
		ptr_size -=
		    (unsigned int) ((unsigned char *) ptr -
				    (unsigned char *) buffer);

		if (ptr_size < 0)
			break;

	}

	gnutls_free(file_data.data);
	fprintf(stderr, "Loaded %d private keys.\n", (int) *privkey_size);

	return key;
}