blob: 3c4571e6d8f64d0b9607508b0f30ed732c59c849 [file]
/*
* Copyright 2018 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#import <Foundation/Foundation.h>
#import <XCTest/XCTest.h>
#include "test/gtest.h"
#include <vector>
#import "api/peerconnection/RTCCertificate.h"
#import "api/peerconnection/RTCConfiguration+Private.h"
#import "api/peerconnection/RTCConfiguration.h"
#import "api/peerconnection/RTCDtlsFingerprint.h"
#import "api/peerconnection/RTCIceServer.h"
#import "api/peerconnection/RTCMediaConstraints.h"
#import "api/peerconnection/RTCPeerConnection.h"
#import "api/peerconnection/RTCPeerConnectionFactory.h"
#import "helpers/NSString+StdString.h"
@interface RTCCertificateTest : XCTestCase
@end
@implementation RTCCertificateTest
- (void)testCertificateIsUsedInConfig {
RTC_OBJC_TYPE(RTCConfiguration) *originalConfig =
[[RTC_OBJC_TYPE(RTCConfiguration) alloc] init];
NSArray *urlStrings = @[ @"stun:stun1.example.net" ];
RTC_OBJC_TYPE(RTCIceServer) *server =
[[RTC_OBJC_TYPE(RTCIceServer) alloc] initWithURLStrings:urlStrings];
originalConfig.iceServers = @[ server ];
// Generate a new certificate.
RTC_OBJC_TYPE(RTCCertificate) *originalCertificate =
[RTC_OBJC_TYPE(RTCCertificate) generateCertificateWithParams:@{
@"expires" : @100000,
@"name" : @"RSASSA-PKCS1-v1_5"
}];
// Store certificate in configuration.
originalConfig.certificate = originalCertificate;
RTC_OBJC_TYPE(RTCMediaConstraints) *contraints =
[[RTC_OBJC_TYPE(RTCMediaConstraints) alloc]
initWithMandatoryConstraints:@{}
optionalConstraints:nil];
RTC_OBJC_TYPE(RTCPeerConnectionFactory) *factory =
[[RTC_OBJC_TYPE(RTCPeerConnectionFactory) alloc] init];
// Create PeerConnection with this certificate.
RTC_OBJC_TYPE(RTCPeerConnection) *peerConnection =
[factory peerConnectionWithConfiguration:originalConfig
constraints:contraints
delegate:nil];
// Retrieve certificate from the configuration.
RTC_OBJC_TYPE(RTCConfiguration) *retrievedConfig =
peerConnection.configuration;
// Extract PEM strings from original certificate.
std::string originalPrivateKeyField =
[[originalCertificate private_key] UTF8String];
std::string originalCertificateField =
[[originalCertificate certificate] UTF8String];
// Extract PEM strings from certificate retrieved from configuration.
RTC_OBJC_TYPE(RTCCertificate) *retrievedCertificate =
retrievedConfig.certificate;
std::string retrievedPrivateKeyField =
[[retrievedCertificate private_key] UTF8String];
std::string retrievedCertificateField =
[[retrievedCertificate certificate] UTF8String];
// Check that the original certificate and retrieved certificate match.
EXPECT_EQ(originalPrivateKeyField, retrievedPrivateKeyField);
EXPECT_EQ(retrievedCertificateField, retrievedCertificateField);
// The fingerprints are derived from the certificate, so they survive the
// round trip through the configuration.
NSArray<RTC_OBJC_TYPE(RTCDtlsFingerprint) *> *originalFingerprints =
[originalCertificate getFingerprints];
NSArray<RTC_OBJC_TYPE(RTCDtlsFingerprint) *> *retrievedFingerprints =
[retrievedCertificate getFingerprints];
XCTAssertEqual(originalFingerprints.count, 1u);
XCTAssertEqual(retrievedFingerprints.count, 1u);
XCTAssertEqualObjects(originalFingerprints.firstObject.algorithm,
retrievedFingerprints.firstObject.algorithm);
XCTAssertEqualObjects(originalFingerprints.firstObject.value,
retrievedFingerprints.firstObject.value);
}
- (void)testGeneratedCertificateHasFingerprint {
RTC_OBJC_TYPE(RTCCertificate) *certificate = [RTC_OBJC_TYPE(RTCCertificate)
generateCertificateWithParams:@{@"name" : @"RSASSA-PKCS1-v1_5"}];
NSArray<RTC_OBJC_TYPE(RTCDtlsFingerprint) *> *fingerprints =
[certificate getFingerprints];
XCTAssertEqual(fingerprints.count, 1u);
RTC_OBJC_TYPE(RTCDtlsFingerprint) *fingerprint = fingerprints.firstObject;
// The algorithm is an IANA hash function textual name, e.g. "sha-256".
NSPredicate *algorithmPredicate =
[NSPredicate predicateWithFormat:@"SELF MATCHES %@", @"[a-z0-9\\-]+"];
XCTAssertTrue([algorithmPredicate evaluateWithObject:fingerprint.algorithm],
@"Unexpected algorithm format: %@",
fingerprint.algorithm);
// The value is colon-separated hexadecimal per RFC 4572, e.g. "AB:CD:...".
NSPredicate *valuePredicate = [NSPredicate
predicateWithFormat:@"SELF MATCHES %@", @"([0-9A-F]{2}:)+[0-9A-F]{2}"];
XCTAssertTrue([valuePredicate evaluateWithObject:fingerprint.value],
@"Unexpected fingerprint value format: %@",
fingerprint.value);
}
- (void)testCertificateFromInvalidPemHasNoFingerprint {
// A certificate built from PEM strings that are not valid certificates has
// no computable fingerprint.
RTC_OBJC_TYPE(RTCCertificate) *certificate =
[[RTC_OBJC_TYPE(RTCCertificate) alloc] initWithPrivateKey:@"private"
certificate:@"certificate"];
XCTAssertEqual([certificate getFingerprints].count, 0u);
}
@end